通过O_DIRECT读取是否首先刷新脏页面?

时间:2018-09-21 08:26:54

标签: linux filesystems posix page-caching

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

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吗? (显然,当前没有打开该文件的其他文件)

在Linux上进行的一些简单测试似乎表明是的,在通过O_DIRECT进行读取之前,write调用中的脏页将被刷新到磁盘上,但是我似乎在任何地方都找不到这种情况。就我所知,这可能完全是巧合,但我不知道在其他类似POSIX的平台上会发生什么。我至少想得到一些“确凿的证据”。

您为什么要这样做?

这是在应用程序中分发要缓存的大文件的上下文中。收到文件的新部分后,我想验证新部分。我看到使用O_DIRECT有两个好处:首先,我不仅检查数据是否已正确接收,而且可以从存储介质中正确检索。没有O_DIRECT,几乎可以保证我只是从页面缓存中获取数据。为了在没有O_DIRECT的情况下达到相同的效果,我不得不在Linux上使用诸如sync_file_range之类的非便携式调用来将数据获取到磁盘,然后通过madvise从页面缓存中刷新数据,最后读取回来了。 (因为我曾经学习过一种很难的方法,即在脏页上用madvise调用MADV_DONTNEED本质上是一种小问题)。
但是,如果有人对此有更优雅的建议,我会非常高兴。 :-)

1 个答案:

答案 0 :(得分:0)

  

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

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

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

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