如果我打开一个文件O_DIRECT
标志,这是否意味着每当对该文件的写入(阻塞模式)返回时,数据都在磁盘上?
(这个答案适用于 Linux - 其他操作系统可能有不同的警告/语义)
我们先从子问题开始:
如果我打开带有 O_DIRECT 标志的文件,是否意味着每当对该文件的写入(阻塞模式)返回时,数据都在磁盘上?
No (as @michael-foukarakis 评论) - 如果您需要保证您的数据已到达非易失性您必须使用/添加其他东西的存储。
O_DIRECT 的真正含义是什么?
It's a hint您希望您的 I/O 绕过Linux内核的缓存。实际发生的情况取决于以下因素:
- 磁盘配置
- 无论您是打开块设备还是文件系统中的文件
- If using a file within a filesystem
- 使用的确切文件系统以及文件系统和文件上使用的选项
- 您是否已正确对齐 I/O
- 文件系统是否必须进行新的块分配以满足您的 I/O
- 如果底层磁盘是本地的,那么在到达磁盘块设备之前,内核存储堆栈中有哪些层
- Linux内核版本
- ...
上面的列表并不详尽。
在“最佳”情况下,设置O_DIRECT
将避免在传输数据时制作额外的数据副本,并且调用将在传输完成后返回。当直接打开“真实”本地磁盘的块设备时,您更有可能遇到这种情况。如前所述,即使是这个属性不保证成功的数据write()
通话不会突然断电。如果数据从 RAM DMA 到非易失性存储(例如电池支持的 RAID 控制器)或者 RAM 本身是持久存储,那么您may保证数据能够在断电情况下稳定存储。要知道是否属于这种情况,您必须验证您的硬件堆栈,这样您就不能一般地假设这种情况。
在“最坏”的情况下,O_DIRECT
即使设置没有被拒绝并且后续调用“成功”,也可能没有任何意义。有时 Linux 存储堆栈中的东西(例如certain文件系统设置)可以选择忽略它,因为它们必须执行的操作或者因为您不满足要求(这是合法的),而只是默默地执行缓冲 I/O(即写入缓冲区/满足从已缓冲的读取)数据)。目前尚不清楚是否会做出额外的努力来确保已确认写入的数据至少“与设备一起”(但在O_DIRECT
克里斯托夫·赫尔维格 (Christoph Hellwig) 的帖子指出the O_DIRECT回退将确保数据至少已发送到设备)。进一步复杂化的是使用O_DIRECT
暗示与文件元数据无关,所以即使 writedata通过呼叫完成“与设备一起”,关键文件元数据(例如文件的大小,因为您正在执行附加操作)可能不是。因此,您实际上可能无法获取您认为在崩溃后已传输的数据(它可能会显示被截断,或全部为零等)。
虽然简短的测试可以使它看起来像使用的数据O_DIRECT
单独总是意味着写入返回后数据将位于磁盘上,更改内容(例如使用 Ext4 文件系统而不是 XFS)可能会以非常激烈的方式削弱实际实现的效果。
当您提到“保证数据”(而不是元数据)时,您可能正在寻找O_DSYNC
/fdatasync()
?如果您想保证元数据也被写入,您将不得不查看O_SYNC
/fsync()
.
参考
-
Ext4 Wiki:澄清 Direct IO 的语义。还包含有关什么的注释
O_DIRECT
在一些非 Linux 操作系统上也是如此。
- “[PATCH 1/1 linux-next] ext4:向补丁添加兼容性标志检查”LKML 线程有来自 Ext4 领导开发人员 Ted Ts'o 的回复,谈论如何进行文件系统可以回退到缓冲 I/OO_DIRECT而不是失败open() call.
- 在“ubifs:允许 O_DIRECT”LKML 线程 Btrfs 首席开发人员 Chris Mason 中表示Btrfs 在以下情况下求助于缓冲 I/O:O_DIRECT对压缩文件有要求.
-
Linux 上的 ZFS 提交消息讨论的语义O_DIRECT在不同场景下。另请参阅(2020 年中期撰写本文时)提出新的O_DIRECTLinux 上 ZFS 的语义(交互作用很复杂,无法简单解释)。
-
Linux open(2) 手册页(搜索
O_DIRECT
in the 描述部分和注释部分)
-
确保数据到达磁盘绿网文章
- 臭名昭著Linus Torvalds O_DIRECT LKML 线程摘要(有关更多上下文,您可以看到完整的 LKML 线程)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)