【问题标题】:shortnames and parallel file copy短名称和并行文件副本
【发布时间】:2018-11-16 02:36:36
【问题描述】:

我正在处理以下代码:

  • 枚举源目录和目标目录并生成 {src, dst} 对

  • ...每一对都被发送到一个工作线程池

  • ...执行工作,例如“将src复制到dst”

(所有这些都被简化了很多)。

问题:

当文件被创建时,它还会获得一个短名称,它可以与源目录中的另一个文件相同(名称冲突),这会导致各种效果(取决于操作的顺序)。例如,复制两个文件 my file 和 MYFILE~1 可以在目标中生成 2 或 1 个文件(取决于你的运气),可能包含损坏的内容(在后一种情况下)。

问题:

如何避免此类碰撞产生的问题?如果有一个函数可以创建/打开忽略短名称的文件...

注意事项:

  • 无法假设短名称的生成方式。不同的系统采用不同的方案(见this)

  • 即使您以顺序方式(一个接一个)运行这些作业——它们也需要按顺序执行,这取决于短名称生成逻辑(未知)。另外,这意味着在运行任何作业之前在内存中加载和排序/等整个目录

  • 源和目标都可能非常大(可能是数百万个文件),(如果可能)我想避免将整个目录加载到内存中或多次枚举它

  • 无法关闭目标卷中的短名称生成,并且不能将其作为要求(另外,关闭它并不会删除现有的短名称)

  • 应用仅限于 Win32 API 和 NT API

编辑:在我看来,在一般情况下,即使所有事情都发生在一个线程上,您也无法做到这一点——仅仅是因为无论您选择什么顺序,都会有一个短名称生成方案以及一组保证在处理过程中产生冲突的文件名。

如果这是正确的——系统实用程序如何复制文件?他们是否会在复制完成后假设一些短名称或执行“验证和修复差异”?

【问题讨论】:

  • 您确定您的诊断正确吗?我真的怀疑文件系统会创建两个具有相同短名称的文件。
  • 不,不会。复制my file(具有MYFILE~2 短名称)将在dst 目录中创建my file(可能带有MYFILE~1 短名称)。如果在此之后您复制MYFILE~1(没有短名称)-它将覆盖上一步创建的文件并且(取决于许多事情)可能会损坏它的数据(如果复制并行发生)。
  • 你为什么要使用短文件名?使用完整文件名复制文件。在某些文件系统上,您甚至可以关闭短文件名的生成。
  • @Remy 我认为提问者是在使用完整文件名进行复制,但是在目标端生成的短文件名与源端不同,进而干扰后续操作。
  • @C.M.我想知道为什么您使用线程来执行不受 CPU 限制的操作

标签: winapi filesystems ntdll


【解决方案1】:

问题基本上归结为:dst 永远不应该通过shortname 打开。

例如(在NT API的情况下)可以这样实现:

  • 打开时(NtCreateFile(),不截断)dst 使用 FILE_OPEN_IF 作为 CreateDisposition

  • 在成功检查IoStatusBlock::Information 是否已创建文件 (FILE_CREATED)

    • 如果是 - 不需要做任何事情(不可能通过短名称创建文件)

    • 如果没有——通过NtQueryInformationFile(FileNameInformation)检查当前文件名

      • 如果名称与提供给NtCreateFile() 的名称不同(区分大小写!) -- 错误

并行进程可以在您打开文件后立即重命名文件,但我会将其视为错误。

错误可能导致几次重试,然后出现硬故障(需要人工注意)。手动(甚至以编程方式)解决问题应该不会太难,因为NtQueryInformationFile()返回了冲突文件的名称。

附:可以采取其他步骤来防止/减少冲突。例如,如果已知短名称生成逻辑 -- dst 对象可以按特定顺序处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 2022-11-29
    • 2014-01-08
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    相关资源
    最近更新 更多