当 Windows XP 和 Vista 中的磁盘策略设置为在硬盘上启用写入缓存时,有没有办法刷新刚刚写入的文件,并确保它已提交到磁盘?
我想在 C++ 中以编程方式执行此操作。
关闭文件确实会在应用程序级别执行刷新,但不会在操作系统级别执行。如果在关闭文件后、但在操作系统刷新磁盘写入缓存之前从 PC 上断电,则即使文件已关闭,文件也会丢失。
当 Windows XP 和 Vista 中的磁盘策略设置为在硬盘上启用写入缓存时,有没有办法刷新刚刚写入的文件,并确保它已提交到磁盘?
我想在 C++ 中以编程方式执行此操作。
关闭文件确实会在应用程序级别执行刷新,但不会在操作系统级别执行。如果在关闭文件后、但在操作系统刷新磁盘写入缓存之前从 PC 上断电,则即使文件已关闭,文件也会丢失。
.NET FileStream.Flush() 不会刷新该文件内容的 Windows 缓存;Flush() 仅刷新 .NET 内部文件缓冲区。在 .NET 4.0 中,Microsoft 通过向 Flush() 添加一个可选参数来解决此问题,如果设置为 true,则会调用 FlushFileSystemBuffers。在 .NET 3.5 及以下版本中,您唯一的选择是通过 pinvoke 调用 FlushFileBuffers。有关如何执行此操作,请参阅 MSDN 的FileStream.Flush社区评论。
你还没有指定开发环境,所以:
IO 流有一种.Flush
方法可以满足您的需求。
有一个FlushFileBuffers
调用,它将文件句柄作为参数。
编辑(基于 OA 的评论): FlushFileBuffers 不需要管理权限;只有当传递给它的句柄是卷的句柄,而不是单个文件的句柄时,它才会这样做。
您还应该注意,您的数据可能不会被刷新到实际磁盘,即使在调用框架 API 的刷新方法时也是如此。
调用 flush 方法只会告诉内核将其页面刷新到磁盘。但是,如果您打开了磁盘写入缓存,则可以无限期地延迟实际的写入过程。
为了确保您的数据被写入物理层,您必须关闭操作系统中的写入缓存。在处理大量小型 io 操作时,这通常会导致性能损失高达一到两个数量级。基于电池的支持 (UPS) 或接受命令以刷新磁盘写入缓存的磁盘是处理此问题的另一种选择。
从 microsoft 文档中,您将使用_flushall并在 COMMODE.OBJ 中链接以确保所有缓冲区都已提交到磁盘。
见这里:https ://jeffpar.github.io/kbarchive/kb/066/Q66052/
当您最初使用 fopen 打开文件时,将“c”模式选项作为最后一个选项:
fopen( path, "wc") // w - write mode, c - allow immediate commit to disk
然后当你想强制刷新到磁盘时,调用
_flushall()
我们在打电话之前打了这个电话
fclose()
我们遇到了您描述的确切问题,这种方法解决了它。
请注意,这种方法不需要管理权限,正如其他人所提到的那样,这FlushFileBuffers
确实需要。
从上面的网站:
“Microsoft C/C++ 7.0 版为 fopen() 函数引入了“c”模式选项。当应用程序打开文件并指定“c”模式时,运行时库将文件缓冲区的内容写入磁盘应用程序调用 fflush() 或 _flushall() 函数。"