我发现当遇到内存不足 OOM 情况时,我的 linux box UI 会完全冻结很长时间。
我已经设置了 magic-sysrq-key,然后使用 echo 1 | tee /proc/sys/kernel/sysrq
并遇到 OOM->UI 无响应情况,能够Alt-Sysrq-f
按日志显示的那样dmesg
导致 OOM 终止/终止进程,从而解决 OOM 情况。
我的问题是现在。为什么 Linux 会像 GUI 冻结一样变得无响应,但似乎没有触发相同的 OOM-Killer,而我是通过Alt-Sysrq-f
组合键手动触发的?
考虑到在 OOM“冻结”情况下,系统反应迟钝,甚至不允许及时(< 10秒)响应Ctrl-Alt-F3
(切换到 tty3),我不得不假设内核必须意识到其无响应,但仍然本身并没有调用Alt-Sysrq-f
OOM-Killer ,为什么?
这些是可能对所描述的行为产生影响的一些设置。
$> mount | grep memory
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
$> cat /sys/fs/cgroup/memory/memory.oom_control
oom_kill_disable 0
under_oom 0
oom_kill 0
据我了解,内存 cgroup 既没有激活也没有禁用 OOM(显然必须有充分的理由来激活和禁用 OOM_kill,或者也许我无法正确解释输出,而且还under_oom 0
有些不清楚,仍然)
答案1
OOM-killer 不会自动调用的原因是,尽管系统已经完全变慢并且没有响应,但接近内存不足y,实际上并没有达到内存不足的情况。
过于简单化,几乎满的内存包含 3 种类型的数据:
- 内核数据,这是必不可少的
- 基本进程数据页(例如进程仅在 RAM 中创建的任何数据)
- 非必要的进程数据页(例如可执行文件代码等数据,在磁盘/文件系统中有一个副本,并且当前映射到内存时可以在使用时从磁盘“重新读取”)
在内存匮乏的情况下,据我所知,Linux 内核是kswapd0
内核线程,为了防止数据丢失和功能丢失,不能丢弃 1. 和 2. ,但可以自由地至少暂时删除那些映射到-内存文件来自 RAM 的数据,这些数据是当前未运行的进程的形式。
虽然这是涉及磁盘抖动,不断地丢弃数据并从磁盘重新读取数据,可以被认为是有帮助的,因为它避免了,或者至少推迟了必要的删除/终止进程以及释放但也丢失了其内存,它有一个高的价格:性能。
[load pages from disk to ram with code of executable of process 1]
[ run process 1 ]
[evict pages with binary of process 1 from ram]
[load pages from disk to ram with code of executable of process 2]
[ run process 2 ]
[evict pages with binary of process 2 from ram]
[load pages from disk to ram with code of executable of process 3]
[ run process 3 ]
[evict pages with binary of process 3 from ram]
....
[load pages from disk to ram with code of executable of process 1]
[ run process 1 ]
[evict pages with binary of process 1 from ram]
显然 IO 成本很高,并且系统可能会变得无响应,尽管从技术上讲它已经尚未完全用完的記憶。
然而,从用户的角度来看,挂起/冻结以及由此产生的无响应 UI 可能并不比简单地终止进程(例如浏览器选项卡的进程,其内存使用量很可能是根本原因/罪魁祸首)更好。首先。)
正如问题所示,这就是魔法 SysRq 键手动启动 OOM 的触发器似乎很棒,因为 Magic SysRq 受系统无响应的影响较小。
虽然可能存在保留流程很重要的用例(表现)成本,对于桌面来说,用户可能更喜欢 OOM 杀手而不是冻结的 UI。有一个补丁声称可以在这种情况下从内存中免除干净映射的文件系统支持的文件在 stackoverflow 上回答。
答案2
您可以在压力测试期间查看文件 /sys/fs/cgroup/memory/memory.oom_control。
或者
您可以查看它的最后修改日期,看看它是否在上次锁定时间前后被更改。这会告诉你它是否正在尝试完成它的工作。
under_oom 0
那是你的问题:
under_oom 0 or 1 (if 1, the memory cgroup is under OOM, tasks may
be stopped.)
如果设置为 1,则表示受 oom 控制。已启用。
如果设置为 0,则不受 oom 控制。残疾人。