d33*_*tah 2 linux caching posix system-calls linux-kernel
我注意到在执行如下命令后,我遇到了系统响应能力(桌面 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);实际上会按照我的预期运行并解决这里的问题吗?
鉴于我只会使用 file_larger_than_ram.bin 一次,有没有办法提示内核不要缓存该文件?
O_DIRECT据我所知,通过系统调用的标志是可能的open。但该标志带有额外的限制(例如文件偏移和用户空间内存缓冲区对齐),这可能会导致问题。它们在测试中没有给我带来问题,但文档说该行为是特定于设备/文件系统的。因此我更改了代码以使用fadvise().
(此外,我观察到一些性能异常(read()/write()太快),这表明即使O_DIRECT某些数据有时也会被缓存。YMMV。)
我听说我可以使用 fadvise 来实现这一点,但我不确定 [...]
我也不清楚,所以我检查了内核源代码。fadvise()调用with的作用POSIX_FADV_DONTNEED是从缓存中取出对应的数据。我还没有看到任何表明该标志是粘性的并且适用于所有文件操作的内容。(这就是我检查源代码的原因:我知道 Linux总是通过缓存执行 I/O,而O_DIRECTCache 是替代方案。粘性POSIX_FADV_DONTNEED不适合该范例。)
换句话说,要在读取期间释放缓存,您需要:
跟踪之前的文件偏移量read()
之后read(),调用fadvise(POSIX_FADV_DONTNEED)您刚刚读取的数据范围。
为了获得最佳结果,您必须读取页对齐块中的数据。I/O 缓存是基于页的,并将fadvise()指定的数据范围映射到页列表中。未对准会导致额外的read()s(并损害性能),但除此之外是无害的。
对于编写它来说有点复杂:我观察到fadvise(POSIX_FADV_DONTNEED)如果在write(). 必须调用fsync()/fdatasync()来强制写入数据,从而取消固定缓存条目,然后才调用 / 来fadvise(POSIX_FADV_DONTNEED)释放它们。
PS 据我了解内核代码,dd@AlexHoppus 链接的技巧应该有效。例如cat file; dd if=file of=/dev/null iflag=nocache- 该cat调用会将文件放入缓存中,dd从缓存中读取它,然后从缓存中丢弃它。该fadvise(POSIX_FADV_DONTNEED)操作对全局缓存进行操作,因此谁/何时读取数据无关紧要,无论如何它都会丢弃它们。