OOM 杀手不工作?

Sal*_*lem 50 kernel

据我了解,当系统接近没有可用内存时,内核应该开始杀死进程以重新获得一些内存。但在我的系统中,这根本不会发生。

假设一个简单的脚本只分配了比系统中可用内存多得多的内存(例如,一个包含数百万个字符串的数组)。如果我运行这样的脚本(作为普通用户),它只会获取所有内存,直到系统完全冻结(只有 SysRQ REISUB 有效)。

这里奇怪的部分是,当计算机死机时,硬盘驱动器 LED 灯会亮起并保持这种状态,直到计算机重新启动,无论我是否安装了交换分区!

所以我的问题是:

  1. 这种行为正常吗?奇怪的是,作为普通用户执行的应用程序可以通过这种方式使系统崩溃......
  2. 有什么办法可以让 Ubuntu 在这些应用程序获得太多(或最多)内存时自动杀死它们?

附加信息

  • Ubuntu 12.04.3
  • 内核 3.5.0-44
  • RAM:约 3.7GB 从 4GB(与显卡共享)。*

    $ tail -n+1 /proc/sys/vm/overcommit_*
    ==> /proc/sys/vm/overcommit_memory <==
    0
    
    ==> /proc/sys/vm/overcommit_ratio <==
    50
    
    $ cat /proc/swaps
    Filename                Type        Size    Used    Priority
    /dev/dm-1                               partition   4194300 344696  -1
    
    Run Code Online (Sandbox Code Playgroud)

Ter*_*ior 43

官方/proc/sys/vm/*文档

oom_kill_allocating_task

这可以启用或禁用在内存不足的情况下终止触发 OOM 的任务。

如果将其设置为零,则 OOM 杀手将扫描整个任务列表并根据启发式选择要杀死的任务。这通常会选择一个流氓内存占用任务,该任务在被杀死时会释放大量内存。

如果设置为非零,OOM 杀手会简单地终止触发内存不足情况的任务。这避免了昂贵的任务列表扫描。

如果选择了 panic_on_oom,它优先于 oom_kill_allocating_task 中使用的任何值。

默认值为 0。

总结一下,当设置oom_kill_allocating_task为 时1,内核不会扫描您的系统寻找要杀死的进程,这是一项昂贵且缓慢的任务,它只会杀死导致系统内存不足的进程。

根据我自己的经验,当触发 OOM 时,内核没有足够的“强度”来进行此类扫描,从而使系统完全无法使用。

此外,仅仅杀死导致问题的任务会更明显,所以我不明白为什么0默认设置为。

为了测试,您可以只写入正确的伪文件 中/proc/sys/vm/,它将在下次重新启动时撤消:

echo 1 | sudo tee /proc/sys/vm/oom_kill_allocating_task
Run Code Online (Sandbox Code Playgroud)

要永久修复,请将以下内容写入/etc/sysctl.conf或 下的新文件/etc/sysctl.d/,并带有.conf扩展名(/etc/sysctl.d/local.conf例如):

vm.oom_kill_allocating_task = 1
Run Code Online (Sandbox Code Playgroud)

  • @MarkAmery 真正的问题是,即使`vm.admin_reserve_kbytes` 增加到*128 MB*,Linux 不仅会杀死所需的进程,还会开始像智障一样颠簸。设置 `vm.oom_kill_allocating_task = 1` 似乎可以缓解这个问题,但并没有真正解决它(Ubuntu 默认已经处理了 fork 炸弹)。 (4认同)
  • 在 Ubuntu 中它总是设置为 0 吗?因为我记得它曾经自动杀死,但自从几个版本以来它停止这样做。 (3认同)
  • *“此外,仅仅杀死导致问题的任务会更明显,所以我不明白为什么默认情况下它被设置为‘0’。”* - 因为请求内存的进程不一定是那个“导致问题”。如果进程 A 占用了系统内存的 99%,而使用 0.9% 的进程 B 恰好是因运气不好而触发 OOM 杀手的进程,那么 B 并没有“导致问题”并且没有任何意义杀死 B. 将其作为策略风险完全没有问题的低内存进程由于 *不同* 进程的失控内存使用而被偶然杀死。 (3认同)
  • 也许更优雅的`sudo sysctl -w vm.oom_kill_allocating_task=1` (3认同)
  • @skerit 这我真的不知道,但在我 2010 年使用的内核(Debian、Liquorix 和 GRML)中它被设置为 0。 (2认同)

int*_*_ua 12

更新:该错误已修复。

Teresa 的回答足以解决问题并且很好。

此外,我已经提交了一个错误报告,因为这绝对是一个错误的行为。

  • 可能已在 2014 年修复,在 2018 年(和 18.04)OOM 杀手再次无所作为。 (12认同)
  • 我不知道你为什么被否决,但这对我来说听起来也像是内核错误。我今天用它崩溃了一个大型大学服务器并杀死了一些运行数周的进程......不过感谢提交该错误报告! (2认同)

qwr*_*qwr 6

您可以尝试earlyoom,它是一个OOM杀手,它在用户空间中运行,并尝试在OOM情况下杀死最大的进程。