我需要创建一个新的文件句柄,以便对该句柄的任何写操作都可以立即写入磁盘。

额外信息:句柄将是子进程的继承STDOUT,因此我需要该进程的任何输出立即写入磁盘。

在研究CreateFile文档时,FILE_FLAG_WRITE_THROUGH标志看起来完全像我所需要的:



我写了一个非常基本的测试程序,但是,它没有用。
我在CreateFile上使用了该标志,然后在很长的循环中使用了WriteFile(myHandle,...),在大约15秒内写入了大约100MB的数据。 (我添加了一些Sleep())。

然后,我建立了一个专业的监视环境,其中包括在资源管理器中连续命中“F5”。结果:文件停留在0kB,然后在测试程序结束时跳至100MB。

我尝试的下一件事是在每次写入后使用FlushFileBuffers(myHandle)手动刷新文件。如预期的那样,这使观察到的文件大小变得稳定且稳定。

我的问题是,如果没有手动刷新文件,那么FILE_FLAG_WRITE_THROUGH是否应该完成此?我想念什么吗?
在“现实世界”程序中,我无法刷新文件,因为我无法控制正在使用该文件的子进程。

还有FILE_FLAG_NO_BUFFERING标志,出于相同的原因,我无法使用它-无法控制使用句柄的进程,因此我无法根据此标志的要求手动对齐写入。

编辑:
我专门制作了一个单独的项目,用于观察文件大小如何变化。它使用.NET FileSystemWatcher 类。我也写更少的数据-总共大约100kB。

这是输出。查看时间戳记中的秒数。

“内置的无缓冲区”版本:

25.11.2008 7:03:22 PM: 10230 bytes added.
25.11.2008 7:03:31 PM: 10240 bytes added.
25.11.2008 7:03:31 PM: 10240 bytes added.
25.11.2008 7:03:31 PM: 10240 bytes added.
25.11.2008 7:03:31 PM: 10200 bytes added.
25.11.2008 7:03:42 PM: 10240 bytes added.
25.11.2008 7:03:42 PM: 10240 bytes added.
25.11.2008 7:03:42 PM: 10240 bytes added.
25.11.2008 7:03:42 PM: 10240 bytes added.
25.11.2008 7:03:42 PM: 10190 bytes added.

...以及“强制(手动)冲洗”版本(每〜2.5秒调用一次FlushFileBuffers()):
25.11.2008 7:06:10 PM: 10230 bytes added.
25.11.2008 7:06:12 PM: 10230 bytes added.
25.11.2008 7:06:15 PM: 10230 bytes added.
25.11.2008 7:06:17 PM: 10230 bytes added.
25.11.2008 7:06:19 PM: 10230 bytes added.
25.11.2008 7:06:21 PM: 10230 bytes added.
25.11.2008 7:06:23 PM: 10230 bytes added.
25.11.2008 7:06:25 PM: 10230 bytes added.
25.11.2008 7:06:27 PM: 10230 bytes added.
25.11.2008 7:06:29 PM: 10230 bytes added.

最佳答案

在崩溃日志记录的背景下,我也为此感到痛苦。
FILE_FLAG_WRITE_THROUGH仅保证在WriteFile返回之前,您要发送的数据已发送到文件系统。它不能保证它实际上已发送到物理设备。因此,例如,如果在带有此标志的句柄上的ReadFile之后执行WriteFile,则可以确保读取操作将返回您写入的字节,无论它是从文件系统缓存还是从底层设备获取数据。

如果要保证已将数据写入设备,则需要FILE_FLAG_NO_BUFFERING,并伴随所有额外的工作。例如,这些写入必须对齐,因为缓冲区在返回之前一直向下到达设备驱动程序。

知识库在区别上有一个terse but informative article

在您的情况下,如果父进程要比 child 长寿,那么您可以:

  • 使用CreatePipe API创建可继承的匿名管道。
  • 使用CreateFile创建一个设置了FILE_FLAG_NO_BUFFERING的文件。
  • 将管道的可写句柄作为其STDOUT提供给子级。
  • 在父进程中,将管道的可读句柄读取到对齐的缓冲区中,然后将其写入文件中。
  • 关于winapi - Win32 : Write to file without buffering?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/317801/

    10-11 01:53