【问题标题】:Does reading via O_DIRECT flush dirty pages first?通过 O_DIRECT 读取是否首先刷新脏页?
【发布时间】:2019-02-25 14:53:49
【问题描述】:

假设我有一个执行以下操作的简单程序:

fdWrite = open("file", O_WRONLY);
fdRead = open("file", O_RDONLY | O_DIRECT);
writeBuffer = <some data>;
write(fdWrite, writeBuffer);
readBuffer = read(fdRead, sizeof(writeBuffer));

我能保证readBuffer == writeBuffer吗? (显然,鉴于此文件的其他 fd 目前没有打开)

Linux 上的一些简单测试似乎表明,是的,来自 write 调用的脏页将在通过 O_DIRECT 读取之前刷新到磁盘,但我似乎在任何地方都找不到任何提及此场景的内容。据我所知,它的工作可能完全是巧合,而且我不知道在其他类似 POSIX 的平台上会发生什么。至少我想得到一些“确凿的证据”。

你为什么要这样做?

这是在应用程序分发被缓存的大文件的上下文中。收到文件的新部分后,我想验证新部分。我看到使用O_DIRECT 的两个优点:首先,我不仅检查数据是否已正确接收,而且可以从存储介质中正确检索。如果没有O_DIRECT,我几乎可以保证我只是从页面缓存中获取数据。为了在没有O_DIRECT 的情况下达到同样的效果,我必须在Linux 上使用像sync_file_range 这样的不可移植调用来将数据写入磁盘,然后通过madvise 从页面缓存中刷新它,最后再读回它。 (因为我曾经学会了在脏页上用MADV_DONTNEED 调用madvise 本质上是一个无用的方法。
但是,如果有人对此有更优雅的建议,我会全力以赴。 :-)

【问题讨论】:

  • 来自 man open(2):“应用程序应避免将 O_DIRECT 和普通 I/O 混合到同一个文件,尤其是同一个文件中的重叠字节区域。即使文件系统正确处理一致性在这种情况下的问题......”。所以看起来它会起作用,但应该避免。
  • 这是针对网络文件系统的吗?如果您在单节点机器上执行所有这些操作,那么在时间 t1 写入之后在时间 t2 的任何读取都可以保证提供来自页面缓存的最新数据,而无需 fsync。您是否正在寻找读取的正确性或在磁盘上持久化数据(在这种情况下 fsync 才有意义)?

标签: linux filesystems posix page-caching


【解决方案1】:

我不仅在检查数据是否已正确接收,而且可以从存储介质中正确检索。

为此,您需要取消设备完成的缓存。

大多数设备数据缓存都比较小——兆字节而不是千兆字节。[*] 如果你的大文件足够大,你可以执行 write()+fsync(),你会溢出设备缓存。然后使用您的 DONTNEED 将其从 Linux 页面缓存中删除。然后您可以从设备中重新读取()文件。

[*] 一些虚拟化环境打破了这种期望。 https://unix.stackexchange.com/questions/420299/why-is-sync-drop-caches-not-dropping-caches/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    相关资源
    最近更新 更多