加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

winapi – Win32:写入文件不缓冲?

发布时间:2020-12-14 04:32:31 所属栏目:Windows 来源:网络整理
导读:我需要创建一个新的文件句柄,以便对该句柄的任何写入操作立即写入磁盘. 额外信息:句柄将是子进程的继承STDOUT,因此我需要该进程的任何输出立即写入磁盘. 学习CreateFile文档,FILE_FLAG_WRITE_THROUGH标志看起来就像我所需要的: Write operations will not
我需要创建一个新的文件句柄,以便对该句柄的任何写入操作立即写入磁盘.

额外信息:句柄将是子进程的继承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.>在父进程中,从管道的可读手柄读取到对齐的缓冲区中,并将其写入文件.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读