11

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

在支持文档中异步磁盘 I/O 在 Windows NT、Windows 2000 和 Windows XP 上显示为同步时说:

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

在 MSDN 中,SetFileValidDataSets the valid data length of the specified file.

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

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

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

4

4 回答 4

25

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

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

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

附录:

  • 稀疏文件的规则不同。

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

于 2012-09-03T03:08:26.653 回答
6

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

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

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

于 2013-11-05T00:38:37.810 回答
3

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

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

于 2014-11-21T09:40:38.587 回答
-1

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

参考 MSDN ,

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

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

于 2013-01-27T03:24:40.033 回答