6

当 Windows XP 和 Vista 中的磁盘策略设置为在硬盘上启用写入缓存时,有没有办法刷新刚刚写入的文件,并确保它已提交到磁盘?

我想在 C++ 中以编程方式执行此操作。

关闭文件确实会在应用程序级别执行刷新,但不会在操作系统级别执行。如果在关闭文件后、但在操作系统刷新磁盘写入缓存之前从 PC 上断电,则即使文件已关闭,文件也会丢失。

4

6 回答 6

8

.NET FileStream.Flush() 不会刷新该文件内容的 Windows 缓存;Flush() 仅刷新 .NET 内部文件缓冲区。在 .NET 4.0 中,Microsoft 通过向 Flush() 添加一个可选参数来解决此问题,如果设置为 true,则会调用 FlushFileSystemBuffers。在 .NET 3.5 及以下版本中,您唯一的选择是通过 pinvoke 调用 FlushFileBuffers。有关如何执行此操作,请参阅 MSDN 的FileStream.Flush社区评论。

于 2011-07-18T22:22:25.197 回答
4

您不应该在关闭文件时修复此问题。Windows 将缓存,除非您打开传递FILE_FLAG_WRITE_THROUGH给 CreateFile() 的文件。

您可能还想通过FILE_FLAG_NO_BUFFERING;这告诉 Windows 不要在缓存中保留字节的副本。

根据 MSDN 上的 CreateFile 文档,这比 FlushFileBuffers() 更有效。

另请参阅MSDN 上的文件缓冲文件缓存

于 2009-05-06T15:37:33.063 回答
2

你还没有指定开发环境,所以:

。网

IO 流有一种.Flush方法可以满足您的需求。

Win32 API

有一个FlushFileBuffers调用,它将文件句柄作为参数。

编辑(基于 OA 的评论): FlushFileBuffers 不需要管理权限;只有当传递给它的句柄是卷的句柄,而不是单个文件的句柄时,它才会这样做。

于 2008-10-06T08:43:57.020 回答
2

您还应该注意,您的数据可能不会被刷新到实际磁盘,即使在调用框架 API 的刷新方法时也是如此。

调用 flush 方法只会告诉内核将其页面刷新到磁盘。但是,如果您打开了磁盘写入缓存,则可以无限期地延迟实际的写入过程。

为了确保您的数据被写入物理层,您必须关闭操作系统中的写入缓存。在处理大量小型 io 操作时,这通常会导致性能损失高达一到两个数量级。基于电池的支持 (UPS) 或接受命令以刷新磁盘写入缓存的磁盘是处理此问题的另一种选择。

于 2009-05-06T14:58:23.577 回答
1

从 microsoft 文档中,您将使用_flushall并在 COMMODE.OBJ 中链接以确保所有缓冲区都已提交到磁盘。

于 2008-10-06T10:29:59.553 回答
0

见这里: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() 函数。"

于 2019-07-17T15:56:10.763 回答