Linux 读取文件,但提示内核不要缓存其内容?

Linux 读取文件,但提示内核不要缓存其内容?,linux,caching,linux-kernel,posix,system-calls,Linux,Caching,Linux Kernel,Posix,System Calls,我注意到在执行如下命令后,系统的响应性(桌面GUI)出现了重大问题: cat文件_大于_ram.bin |/简单过程 我的理论是,这会导致Linux内核丢弃它目前保存在RAM未使用部分的文件缓存。同时,进程需要访问它们处理的数据,因此在执行上述命令后,它们必须再次加载文件。考虑到我只会使用一次大于ram.bin的文件,有没有办法提示内核不要缓存该文件?我听说我可以用fadvise来做这个,但我不确定fadvise64(2)说了什么: POSIX_FADV_不需要尝试释放与指定区域关联的缓存页。这

我注意到在执行如下命令后,系统的响应性(桌面GUI)出现了重大问题:

cat文件_大于_ram.bin |/简单过程

我的理论是,这会导致Linux内核丢弃它目前保存在RAM未使用部分的文件缓存。同时,进程需要访问它们处理的数据,因此在执行上述命令后,它们必须再次加载文件。考虑到我只会使用一次大于ram.bin的
文件,有没有办法提示内核不要缓存该文件?我听说我可以用
fadvise
来做这个,但我不确定
fadvise64(2)
说了什么:

POSIX_FADV_不需要尝试释放与指定区域关联的缓存页。这是有用的,例如 流式处理大文件。程序可以周期性地请求内核 释放已使用的缓存数据,以便更有用 缓存页不会被丢弃

将应用
fdadvision(输入描述,0,0,POSIX\u FADV\u DONTNEED)实际按照我的预期操作并在这里解决问题

考虑到我只会使用一次大于ram.bin的文件,有没有办法提示内核不要缓存该文件

据我所知,通过
O_DIRECT
标志进入
open
syscall,这是可能的。但该标志还带有其他限制(例如,文件偏移量和用户空间内存缓冲区对齐),这可能会导致问题。他们在测试中没有给我带来问题,但是文档中说这种行为是特定于设备/文件系统的。因此,我将代码更改为使用
fadvise()

(此外,我还观察到一些性能异常现象(读()
/
write()
速度太快),这表明即使使用
O_DIRECT
有时也会缓存一些数据。YMMV。)

我听说我可以使用fadvise,但我不确定[…]

我也不清楚,所以我检查了内核源代码。使用
POSIX_FADV_DONTNEED
调用
fadvise()
的效果是从缓存中删除相应的数据。我没有看到任何迹象表明该标志是粘性的,适用于所有文件操作。(这就是我检查源代码的原因:我知道Linux总是通过缓存执行I/O,而
O_DIRECT
则是另一种选择。粘性
POSIX_FADV_DONTNEED
不适合这种模式。)

换句话说,要在读取期间释放缓存,您需要:

  • 在执行
    read()

  • read()
    之后,对刚刚读取的数据范围调用
    fadvise(POSIX\u FADV\u DONTNEED)

  • 为了获得最佳结果,您必须读取页面对齐块中的数据。I/O缓存基于页面,并且
    fadvise()
    将指定的数据范围映射到页面列表中。未对准会导致额外的
    read()
    s(并损害性能),但在其他方面是无害的

对于编写,它稍微复杂一点:我观察到,
fadvise(POSIX\u FADV\u DONTNEED)
如果在
write()之后调用,则没有效果。必须调用
fsync()
/
fdatasync()
来强制写入数据,从而取消缓存项的钉扎,然后才调用
fadvise(POSIX\u FADV\u DONTNEED)
来释放它们


另外,就我对内核代码的理解而言,@AlexHoppus链接的
dd
技巧应该是可行的。例如
cat文件;dd if=file of=/dev/null iflag=nocache
-调用
cat
将文件放入缓存,
dd
将从缓存中读取它,然后从缓存中丢弃它。
fadvise(POSIX\u FADV\u DONTNEED)
在全局缓存上运行,因此与谁/何时读取数据无关,它无论如何都会丢弃数据。

检查数据有问题吗?从描述来看,测试所有备选方案似乎都是可行的,这需要很多时间,所以我想如果有人已经知道答案,我会问。看起来“dd”在这里很有用-我提议在猫的基础上增加一个,发现它已经被拒绝了一次。你看到了吗?@AlexHoppus:没有,但它很神奇。谢谢我很乐意引用这个答案,并在回答这个问题时总结一下,我很乐意投票并接受它。