为什么 vm.panic_on_oom = 1 时使用 oom_reaper

为什么 vm.panic_on_oom = 1 时使用 oom_reaper

我从作者那里了解到的:

OOM 杀手目前只允许终止一个任务,希望该任务能够在合理的时间内终止并释放其内存。 (……)

已经表明(例如 Tetsuo Handa),构建打破上述核心假设的工作负载并不难,并且 OOM 受害者可能需要无限的时间才能退出,因为它可能会被阻止在不可中断状态中等待被页面分配器中循环的另一个任务阻止的事件(例如锁定)。

这个补丁通过引入一个专门的内核线程(oom_reaper)来降低这种锁定的可能性,该线程在假设不需要这样的内存的情况下,尝试通过抢先获取 oom 受害者拥有的匿名或换出的内存来回收额外的内存无论如何,当它的所有者被杀死并从用户空间踢出时。

简而言之,oom_reaper 内核线程旨在降低 oom_killer 做出不当决策的概率。

据我了解RHEL 8 文档:

/proc/sys/vm/panic_on_oom 文件包含一个值,该值是控制内存不足 (OOM) 行为的开关。当文件包含 1 时,内核会因 OOM 而发生恐慌并停止按预期运行。

默认值为0,指示内核在系统处于OOM状态时调用oom_killer函数。

简而言之: vm.panic_on_oom = 1 OOM 状态不会触发 oom_killer 启动。

因此,从逻辑上讲,不需要 oom_reaper 拐杖。

但是,无论 vm.panic_on_oom 值如何,oom_reaper 都会在系统 init 时启动(在 linux-5.4 下)。

为什么 ?有什么我错过的吗?即使杀手永远不会被发射,有什么东西使得 oom_reaper 成为必要的吗?如果不是,如何防止 oom_reaper 在 vm.panic_on_oom = 1 时启动?


注1:当然我是从阅读代码如果未设置 CONFIG_MMU 则不会构建它,但这显然不是我的系统上的选项。

答案1

有多种称为“OOM 杀手”等的东西。您禁用了内核集成的最后手段 OOM 杀手功能。这与启动的任何守护进程无关。

多年来,多个系统实用程序已经实施了更智能的方法,可以在内存爆炸进程导致系统无法运行之前将其杀死。您很可能正在处理 systemd OOM 杀手(它确实多次拯救了作者)。

man oomd.conf了解如何配置systemd-oomd。在极端情况下,您实际上想要禁用它(为什么?您只是使您的系统无法恢复!),您可以像任何其他使用systemctl disable xyz.service.

(哦,还有一些针对 COTS NAS 盒的恶意软件,其进程名称oom_reaper也为 ,但这可能不是您要处理的。)

答案2

至于为什么:

因为无论哪个用户态进程能够 oom 系统,在第一个用户态程序运行之前,都需要准备好用于管理 oom 情况的默认框架(oom-killer + oom-reaper)。
也就是说在sysV init 或systemd 组织的启动程序之前。
也就是说,在系统知道 sysctl 值之前,因为这些值是由启动时启动的 sysctl 服务设置的。

此外,此设置可能会在运行时通过 sysctl 甚至 /proc/sys/vm/panic_on_oom 进行更改。

所有这些都使得 vm.panic_on_oom 设置在启动时变得不可预测。

至于如何摆脱它:

如果代码表明如果 CONFIG_MMU = n 则不会构建它,那么(幸运的是)这不是我的拱门的选项。那么阻止 oom_reaper 启动的最直接方法就是简单地注释该 subsys_initcall(oom_init)行。但我仍然不确定副作用。

相关内容