首页 > 解决方案 > 同时使用 Direct-IO 写入和页面缓存读取是否安全?

问题描述

例如,打开一个文件两次,一个 fd 直接 io 写入,另一个 fd 读取页面缓存?

如何定义safe:从 direct-io fd 写入一些数据,然后期望immediately从 page-cache fd读取它们

标签: ccachinglinux-kernelext4page-caching

解决方案


我认为directIO写入文件对于以后对该文件的缓存读取应该是相当安全的,但是读取的性能可能较低(写入的数据未保存在页面缓存中,必须从实际存储中读取)。但确切的代码路径可能取决于使用的文件系统。

这篇文章https://lwn.net/Articles/776801/提到直接 IO 具有失效语义:

至少对于某些文件系统,在页面上执行直接 I/O 读取将强制该页面退出缓存

本书在“写入缓存”部分列出了 3 种写入策略:不写入、直写、回写直接 I/O 可能是write()系统调用的“不写”变体。

对单个文件使用多个 fd 是安全的,因为数据由使用 inode 的 FS 代码管理。两个 fd 都将指向同一个 inode。

2013 年邮件列表中有一个线程https://lists.kernelnewbies.org/pipermail/kernelnewbies/2013-July/008660.html和 TLDR 是:

从内核开发人员的角度来看:内核驱动程序保证页面缓存和使用 O_DIRECT 传输的数据之间的一致性。...

  1. 不要担心页面缓存和使用 O_DIRECT 传输的数据之间的一致性。内核将在 O_DIRECT 写入之后使缓存无效,并在 O_DIRECT 读取之前刷新缓存。
  2. 使用互斥锁或信号量(或众多选项 [1] 中的任何一个)来防止在使用共享文件的 IPC 期间常见的同步问题。

因此,虽然直接写入会从页面缓存中清除文件的已写入部分,但写入器和读取器之间存在一定的竞争可能性。因此,如果您的读者想要获取更新的数据,则需要互斥锁或其他同步。只有在直接 IO write() 系统调用结束后,页面缓存才会被清除。

有时不建议混合使用:https ://medium.com/databasss/on-disk-io-part-1-flavours-of-io-8e1ace1de017 “不鼓励同时使用 Direct IO 和 Page Cache 打开同一个文件,因为即使数据在页面缓存中,也会对磁盘设备执行直接操作,这可能会导致不希望的结果。


推荐阅读