额外信息:句柄将是子进程的继承STDOUT,因此我需要该进程的任何输出立即写入磁盘.
学习CreateFile文档,FILE_FLAG_WRITE_THROUGH标志看起来就像我所需要的:
Write operations will not go through
any intermediate cache,they will go
directly to disk.
我写了一个非常基本的测试程序,而且它不工作.
我使用CreateFile上的标志,然后在长循环中使用WriteFile(myHandle,…),在大约15秒内写入大约100MB的数据. (我添加了一些Sleep()).
然后,我建立了一个专业的监控环境,包括在探险者中不断击中“F5”.结果:文件保持在0kB,然后跳转到100MB关于测试程序结束的时间.
接下来我试过的是用FlushFileBuffers(myHandle)在每次写入之后手动刷新文件.这使得观察到的文件大小变得越来越好,如预期的那样稳定.
我的问题是,那么FILE_FLAG_WRITE_THROUGH是不是没有手动刷新文件呢?我错过了什么吗?
在“真实世界”程序中,我无法刷新文件,因为我无法控制正在使用它的子进程.
还有FILE_FLAG_NO_BUFFERING标志,我不能以同样的原因使用 – 无法控制使用句柄的进程,所以我不能手动对齐这个标志所要求的写入.
编辑:
我已经制定了一个独立的项目,专门用于观察文件的大小如何变化.它使用.NET FileSystemWatcher
类.我也写出更少的数据 – 总共约100kB.
这是输出.查看时间戳中的秒数.
‘builtin no-buffers’版本:
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.
…和“强制(手动)刷新”版本(FlushFileBuffers()每约2.5秒调用):
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返回之前发送到文件系统;它并不保证它实际上被发送到物理设备.所以,例如,如果在具有此标志的句柄上的WriteFile之后执行ReadFile,则可以确保读取将返回您写入的字节,无论它是从文件系统缓存还是从底层设备获取数据.
如果要保证数据已写入设备,则需要FILE_FLAG_NO_BUFFERING,并附带所有的附加工作.这些写入必须对齐,因为在返回之前缓冲区一直到设备驱动程序.
知识库有一个terse but informative article的差异.
在你的情况下,如果父进程要比孩子长,那么你可以:
>使用CreatePipe API创建一个可继承的匿名管道.>使用CreateFile创建一个文件FILE_FLAG_NO_BUFFERING设置.>向孩子提供管道的可写句柄作为其STDOUT.>在父进程中,从管道的可读手柄读取到对齐的缓冲区中,并将其写入文件.