【问题标题】:What does SetFileValidData doing ? what is the difference with SetEndOfFile?SetFileValidData 在做什么? SetEndOfFile 有什么区别?
【发布时间】:2012-08-27 00:30:22
【问题描述】:

我正在寻找一种异步且高效地扩展文件的方法。

在支持文档Asynchronous Disk I/O Appears as Synchronous on Windows NT, Windows 2000, and Windows XP 中说:

注意:应用程序可以进行前面提到的写操作 通过使用更改文件的有效数据长度来异步 SetFileValidData 函数,然后发出 WriteFile。

在 MSDN 中,SetFileValidDataSets the valid data length of the specified file 的函数。

但我还是不明白什么是“有效数据”,它和文件大小有什么区别?

我可以使用SetFilePointerExSetEndOfFile来扩展文件大小,但是SetFileValidData如何做到这一点?

SetFileValidData 不能输入大于文件大小的参数。在这种情况下,SetFileValidData的生活意义是什么?

【问题讨论】:

标签: windows file


【解决方案1】:

当您使用SetEndOfFile 增加文件长度时,逻辑文件长度会发生变化并分配必要的磁盘空间,但实际上并没有数据物理写入文件新部分对应的磁盘扇区。有效数据长度保持不变。

这意味着您可以使用SetEndOfFile 非常快速地制作一个非常大的文件,如果您从文件的新部分读取,您只会得到零。当您将实际数据写入文件的新部分时,有效数据长度会增加。

如果您只是想保留空间,那很好,然后将按顺序将数据写入文件。但是如果你把文件弄得很大,并在接近末尾的地方立即写入数据,则需要将零写入文件的新部分,这将需要很长时间。如果您实际上不需要文件包含零,则可以使用SetFileValidData 跳过此步骤;然后文件的新部分将包含以前删除的文件中的随机数据。

附录:

  • 稀疏文件的规则不同。

  • 您应该在非特权用户具有读取权限的文件上使用SetFileValidData;这可能会泄露属于其他用户的已删除文件的内容。

【讨论】:

  • 这个答案很简洁,应该选对的。
【解决方案2】:

请注意SetEndOfFile() 不会将任何零写入磁盘上任何已分配的扇区,它只是在 MFT 记录中分配空间指针,然后更新整个文件系统的空间位图。但操作系统或 FS 将在其 MFT 记录中记录有效/逻辑文件长度。

如果你把文件从1GB放大到2GB,那么附加的1GB应该全为零,但是FS不会将零写入磁盘,它是指这个文件的有效长度知道1GB应该是零.如果您尝试从这个扩大的 1GB 部分读取,它将直接在 RAM 中填充零,然后反馈给您的应用程序。但是,如果您在这 1GB 部分中写入任何字节,则 FS 必须填充从原始 1GB 偏移量到应用程序尝试写入的当前指针的零,而不是从当前位置到尾部的其他字节文件。同时,它记录了从0到当前位置的有效/逻辑长度,物理大小和分配大小仍然是2GB。

但是,如果您使用SetFileValidData(),FS 会直接将有效长度设置为 2GB,并且不会费心填充任何零。无论您写入哪个位置,它都会写入,但无论您从哪个位置读取,您都可能会读出一些垃圾数据,这些数据之前由其他应用程序在文件扩展到该磁盘空间之前生成。

【讨论】:

    【解决方案3】:

    同意 Harry Johnston 的回答,并且从实践的角度来看,虽然 SetFileValidData 具有性能优势,因为它不需要写入零,但它确实具有安全隐患,因为该文件可能包含来自其他已删除文件的数据。因此需要特殊权限 SE_MANAGE_VOLUME_NAME,如 MSDN 所述:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365544(v=vs.85).aspx

    原因是,如果运行程序的用户帐户没有该权限,使用 SetFileValidData 可以将其他用户的已删除数据暴露到该特定文件的视图中,因此不允许普通用户(非管理员)要做到这一点。即使对于特权用户,他们仍然需要注意在文件系统中使用 ACL(访问控制列表)来保护该文件,使其不与非特权用户共享。

    【讨论】:

      【解决方案4】:

      看来SenEndofFile并没有真正为目标文件分配保留磁盘空间,SetFileValidData负责这项工作。

      Refered to MSDN,

      您可以在非常特定的情况下使用 SetFileValidData 函数创建大文件,以便后续文件 I/O 的性能可以优于其他方法。具体来说,如果文件的扩展部分很大并且将被随机写入,例如在数据库类型的应用程序中,扩展和写入文件所需的时间将比使用 SetEndOfFile 和随机写入更快。

      如果SetEndOfFile真的分配了空间,那么SetFileValidData在随机写入时不会比SetEndOfFile更好。所以SetEndOfFile 可能只是创建一个带有孔的稀疏文件,而SetFileValidData 进行实际分配。

      【讨论】:

      • SetEndOfFile 确实分配了磁盘空间——也就是说,它分配了所需的尽可能多的集群,以独占使用相关文件——但它不会向这些集群写入零。如有必要,将写入零。这是因为分配集群是一项快速操作(仅涉及对主文件表的更改),但写入零需要很长时间,如果随后按顺序写入文件,则会浪费。 SetFileValidData 避免了写零的需要,但需要管理员权限。
      • 感谢您的澄清。但是如果SetEndOfFile确实分配了文件表,那么SetFileValidData如何获得比其他方法更好的性能,或者只是比“SetEndOfFile加写零”更好?那么SetFileValidData 有什么必要成为一个有点多余的接口呢?我的意思是,在SetEndOfFile 之后写零似乎没有帮助。这个问题是否有任何外部证据或官方文件?顺便问一下,POSIX接口有对应的函数吗?
      • 如果你使用 SetEndOfFile 扩展一个文件,然后寻找到最后一个扇区并写入一些数据,操作系统将不得不将零写入文件的其余部分(在前一个有效数据标记之间的任何地方)和新的有效数据标记),否则您可以读取分配扇区的原始内容,其中可能包含属于另一个用户的已删除文件的数据。 SetFileValidData 告诉操作系统不要打扰删除旧数据,但您需要管理员权限才能使用它。
      • 您已经链接到解释这一切的 MSDN 文章;我不确定您所说的“这个问题”是什么意思,因为我认为这种行为不是问题。我不知道 POSIX。
      • 对不起,“这个问题”应该是“这个问题”。 Referring to flexhex,当使用SetEndOfFile 扩展文件时,操作系统可能只是在文件后面附加稀疏的零,特别是如果附录的长度很大,但没有真正分配空间或自动写入零。文件系统只会记住任何稀疏漏洞,并在读取请求覆盖这些稀疏漏洞时从逻辑上返回零。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 1970-01-01
      • 2016-12-01
      • 2017-04-10
      • 1970-01-01
      • 2012-05-01
      • 2010-10-02
      相关资源
      最近更新 更多