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

时间:2015-10-28 11:55:11

标签: linux caching linux-kernel posix system-calls

我注意到在执行这样的命令后,我遇到了系统响应能力(桌面GUI)的主要问题:

cat file_larger_than_ram.bin | ./simple-process

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

  

POSIX_FADV_DONTNEED尝试释放与指定区域关联的缓存页面。例如,这很有用   流式传输大文件。程序可以周期性地请求内核   释放已经使用过的缓存数据,以便更有用   不会丢弃缓存页面。

应用fdadvise (input_desc, 0, 0, POSIX_FADV_DONTNEED);实际上是否符合我的预期并在此处解决问题?

1 个答案:

答案 0 :(得分:2)

  

鉴于我只会使用file_larger_than_ram.bin一次,有没有办法提示内核不要缓存文件?

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

(此外,我观察到一些性能不合规定(read() / write()太快),这表明即使使用O_DIRECT,某些数据有时也会被缓存.YMMV。)< / p>

  

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

我也不清楚,所以我检查了内核源代码。使用fadvise()进行POSIX_FADV_DONTNEED调用的效果是从缓存中删除相应的数据。我还没有看到任何迹象表明该标志是 sticky 并适用于所有文件操作。 (这就是我检查源代码的原因:我知道Linux通过缓存执行I / O 始终O_DIRECT可以替代。粘性POSIX_FADV_DONTNEED没有& #39;适合范式。)

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

  • read()

  • 之前跟踪文件偏移量
  • read()之后,就您刚刚阅读的数据范围致电fadvise(POSIX_FADV_DONTNEED)

  • 为了获得最佳效果,您必须读取页面对齐块中的数据。 I / O缓存是基于页面的,fadvise()将指定的数据范围映射到页面列表中。错位会导致额外read() s(和伤害表现),否则无害。

对于写作来说,它有点复杂:我观察到fadvise(POSIX_FADV_DONTNEED)如果在write()之后立即调用则无效。必须调用fsync() / fdatasync()来强制写入数据,从而取消固定缓存条目,然后再调用fadvise(POSIX_FADV_DONTNEED)来释放它们。

P.S。据我了解内核代码,由@AlexHoppus链接的dd的技巧应该有效。例如cat file; dd if=file of=/dev/null iflag=nocache - cat调用会将文件放入缓存中,dd会从缓存中读取它,然后将其从缓存中丢弃。 fadvise(POSIX_FADV_DONTNEED)在全局缓存上运行,因此无论是谁/何时读取数据都无关紧要,无论如何都会丢弃它们。