如何防止Linux内核在即将耗尽RAM时逐出文件支持的可执行页面?(否则会导致磁盘抖动)

如何防止Linux内核在即将耗尽RAM时逐出文件支持的可执行页面?(否则会导致磁盘抖动),linux,linux-kernel,out-of-memory,Linux,Linux Kernel,Out Of Memory,这样做的目的是防止内核在即将耗尽RAM时(即使没有启用交换,但在OOM killer触发之前)导致大量磁盘读取(有效地冻结系统) 注意:vm.swappiness(sysctl)的值对此没有影响!关闭交换(所有交换分区都关闭)也没有效果 我猜要么答案需要使用某些.config选项重新编译内核(我问了这个问题),我还没有尝试过(因为我不知道怎么做),但很可能需要修补内核(因此为什么这个问题会出现,我把它放在这里错了吗?)。但也许还有其他方法,我不知道 有关何时收回代码页的详细信息,请参阅: 1.此

这样做的目的是防止内核在即将耗尽RAM时(即使没有启用交换,但在OOM killer触发之前)导致大量磁盘读取(有效地冻结系统)

注意:
vm.swappiness
(sysctl)的值对此没有影响!关闭交换(所有交换分区都关闭)也没有效果

我猜要么答案需要使用某些
.config
选项重新编译内核(我问了这个问题),我还没有尝试过(因为我不知道怎么做),但很可能需要修补内核(因此为什么这个问题会出现,我把它放在这里错了吗?)。但也许还有其他方法,我不知道

有关何时收回代码页的详细信息,请参阅:
1.此答案及其下方的注释:
2.答案和大卫·施瓦茨的评论

我将第1点的评论粘贴到这里:

例如,考虑一个零交换和系统为零的情况 内存快用完了。内核将从例如。 Firefox(它可以做到这一点,因为Firefox正在运行可执行代码 已从磁盘加载-可从磁盘加载代码 如有需要,请再试一次)。如果Firefox需要再次访问该RAM N 几秒钟后,CPU生成“硬故障”,迫使Linux 释放一些RAM(例如,从另一个进程获取一些RAM),加载 磁盘中缺少数据,然后允许Firefox像往常一样继续。 这与普通交换非常相似,kswapd0可以做到这一点米科 兰塔莱宁2月15日13:08

事实上,我一直在跟踪这些磁盘抖动情况(由于代码页被逐出,然后重新读取,然后再次逐出,等等)(还有屏幕截图,例如iotop)

编辑:相关问题:
EDIT2:我也在linux内核邮件列表(这里:)上问了这个问题(OP问题),但没有人回答。

EDIT3:找到了一种方法,用问题中的补丁修补内核。

在Linux内核设计中没有直接的答案。 让我在这里分享我的想法

根据Linux内存管理,有两种页面:非页面和文件页面。 匿名页面:匿名页面保存数据/缓冲区。这些页面没有任何文件备份或磁盘备份。例如:kmalloc/vmalloc/malloc缓冲区。 文件页面:这些页面包含文件的内容(DLL、二进制文件的文本段、共享库)。通常保存辅助存储器上可用的数据

代码页(换句话说,文件页)被标记为可回收页,因为这些页可以在任何时候重新生成。 在内存不足的情况下,kswapd试图收回可回收的页面以释放RAM空间。后来,kswapd尝试交换另一个页面以获得更多的可用空间。 如果内存严重不足,将触发OOM killer以终止进程以释放内存

按照这种设计,代码页是内存紧张情况下的第一个目标。 使用交换(关闭交换或更改vm.swappiness)不会有帮助,因为文件页永远不会被交换。由于无法重新生成这些页面,因此仅交换一个页面

这种情况下的主要问题是RAM空间非常少。如果问题仍然存在,则可能需要升级RAM大小

ANDROID已经提出了一种替代这种场景的方法(如您提到的Firefox示例):低内存杀手(LMK)。 Android中间件将应用程序分类为: 前景应用程序 可见应用程序 服务应用程序 缓存的应用程序 隐藏的应用程序 后台应用程序 上面的术语可能不正确,但这就是他们如何对高优先级的前台应用和低优先级的后台应用进行分类。 每当出现内存不足的情况时,LMK就会选择一个低优先级的应用程序/进程/任务并将其杀死。 以你为例,, Firefox不会被杀死,因为它经常被使用,因此它被归类为缓存应用程序


为了避免磁盘抖动,如果中间件确信您的项目有足够的RAM,那么它必须提出这样一种新的设计。

cgroups-v2内存控制器中的memory.min参数应该会有所帮助

也就是说,让我引述:

硬盘保护。如果cgroup的内存使用量在其 有效最小边界,cgroup的内存在 任何条件。如果没有不受保护的可回收内存 如果可用,将调用OOM killer

资料来源:

也就是说,使用内存控制器创建一个“sysdefault”cgroup。 将memory.min参数设置为RAM的大小。
瞧:你的匿名页面可能会被我们交换,但你基于文件的页面永远不会被回收。

你在找吗?@Michael可能吧,但我需要内核为每个可执行文件/lib的代码页面自动/无缝地执行此操作。编辑:也许一个潜在的内核补丁会包含这样的调用?好吧,我找到了一种方法,请参阅内核补丁内部问题。但我不确定它有多好,即使它能完成任务,因为我成功了,而且我是noob;-)您能指出实现这一点的内核代码吗?正如您所说:“代码页(换句话说,文件页)被标记为可回收页,因为这些页可以在任何时间点重新生成。”。因为我想更改它,这样它们就不会被标记。您可以在代码中grep for u_GFP_回收标志分配。一个这样的例子是fs/cachefiles/directory。请给出实现您所说的所有步骤好吗?我试过了,但是
cgroup.controllers
是空的,因此我不能
#echo'+memory>cgroup.subtree\u control
,例如。好的,我通过使
systemd
使用cgroup v2,为3个(全部)cgroup中的每一个设置4GiB
memory.min
:user