刷新磁盘写缓存



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

我想用C++编程实现这一点。

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

.NET FileStream.Flush()不会为该文件内容刷新Windows缓存;Flush()只刷新.NET内部文件缓冲区。在.NET 4.0中,微软通过在Flush()中添加一个可选参数来解决这个问题,如果设置为true,则会调用FlushFileSystemBuffers。在.NET 3.5及以下版本中,您唯一的选择是通过pinvoke调用FlushFileBuffers。请参阅MSDN'sFileStream.Flush社区评论了解如何做到这一点。

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

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

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

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

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

.Net

IO流有一个.Flush方法,可以执行您想要的操作。

Win32 API

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

EDIT(基于OA的评论):FlushFileBuffers不需要管理权限;只有当传递给它的句柄是卷的句柄,而不是单个文件的句柄时,它才会执行此操作。

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

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

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

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

请参阅此处: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()函数。"

您可以使用FileOptions.WriteThrough标志打开/创建文件,这将导致文件绕过任何缓存直接写入磁盘。

例如

var file = File.Open(
    "1.txt",
    new FileStreamOptions
    {
        Options = FileOptions.WriteThrough
    });
// - OR -
var file = new FileStream(
    "1.txt", 
    FileMode.Create, 
    FileAccess.Write, 
    FileShare.None, 
    4096, 
    FileOptions.WriteThrough)

最新更新