当前位置:首页>Linux>【每天一个linux冷知识-3】当内存告急——OOM Killer的生存游戏

【每天一个linux冷知识-3】当内存告急——OOM Killer的生存游戏

  • 2026-10-11 10:09:04
【每天一个linux冷知识-3】当内存告急——OOM Killer的生存游戏

系统卡死了,然后发生了什么?

你曾经遇到过这样的情况吗:某个程序疯狂吃内存,系统响应越来越慢,鼠标几乎动不了,然后突然——像是被人按下了开关——卡死的程序消失了,系统恢复正常。

这不是运气好,也不是程序自己崩溃了。这是Linux内核的最后一根救命稻草:OOM Killer(Out-Of-Memory Killer,内存不足杀手)。

内核的艰难抉择

当系统物理内存耗尽,且swap空间也填满了,内核再也无法为任何进程分配内存时,它面临一个严峻的问题:要么杀掉一些进程,要么整个系统崩溃。

Linux选择前者。OOM Killer会被触发,它的任务很简单:找到一个或多个进程,杀掉它们,释放内存,让系统活下去。

但问题来了:杀谁?

评分机制:谁是最该死的进程?

OOM Killer使用一套评分系统来决定谁该挨刀。每个进程都会被计算一个 oom_score(可以通过 /proc/[pid]/oom_score 查看)。分数越高,被选中的概率越大。

评分的核心因素包括:

  • 内存占用
    :占得越多,分数越高。这很合理——杀掉一个大内存进程,释放的空间最多。
  • 进程运行时间
    :运行时间越短,分数越高。刚启动的短暂进程比运行了好几年的守护进程更值得牺牲。
  • 进程类型
    :内核线程拥有极高的优先级,几乎不会被选上(它们对系统运行至关重要)。
  • 用户权限
    :root用户的进程分数会被略微降低,但不是绝对保护。
  • 手动调整
    :通过 /proc/[pid]/oom_score_adj,你可以手动给进程加减分。范围是-1000到1000。设置为-1000,进程就会变得“不可被杀”。

手动保护你的重要进程

假设你运行着一个关键的数据库服务,你绝对不希望OOM Killer在内存紧张时把它杀掉。你可以这样做:

echo -800 > /proc/数据库进程PID/oom_score_adj

负值会显著降低它的oom_score,让内核优先考虑其他进程。如果你想让一个进程完全免疫,可以用 -1000(注意,不是0)。

反过来,如果你想让某个进程成为“替死鬼”,可以设置正值。

一个常见的误区:swap 设置越大越好?

很多人觉得,既然内存不够会触发OOM,那把swap设大一点不就好了?比如给服务器配个32GB swap。

这不一定明智。当系统开始大量使用swap时,性能会急剧下降——因为磁盘比内存慢几个数量级。系统可能会因为频繁换页而陷入“颠簸”状态(thrashing),响应变得极其缓慢,甚至比直接触发OOM Killer更糟糕。

一个常见的建议是:swap大小设为内存的1到2倍(对于内存较小的系统),或者干脆设为固定值(比如4-8GB)。对于大内存服务器(64GB以上),有时候甚至不需要swap,因为OOM Killer比swap颠簸更可控。

冷门知识点:内存超售与“惰性分配”

Linux默认允许内存超售(overcommit)。什么意思呢?当一个程序申请100MB内存,内核并不会立刻真的给你100MB物理内存,而是先记下“你承诺会用这么多”,等到程序真的去写数据时,才分配物理页面。

这种策略能提高内存利用率,因为很多程序申请的内存其实用不完。但风险在于:当多个程序同时开始实际使用它们承诺的内存时,总需求可能超过物理内存+swap的总和。这时候,OOM Killer就不得不登场了。

你可以通过 /proc/sys/vm/overcommit_memory 控制超售行为:

  • 0
    :启发式超售(默认)
  • 1
    :总是超售
  • 2
    :严格不超售,申请内存不能超过 overcommit_ratio 限制

在某些关键系统(如数据库服务器)中,设置 overcommit_memory=2 可以避免因超售导致的意外OOM,但代价是某些申请内存较多的程序可能会直接失败。

触发OOM Killer之后如何追溯?

当OOM Killer出手时,内核会在系统日志中留下详细的“处决记录”。你可以用 dmesg 或查看 /var/log/messages 找到类似这样的内容:

Out of memory: Kill process 12345 (mysql) score 456 or sacrifice childKilled process 12345 (mysql) total-vm:12345678kB, anon-rss:8765432kB

这些信息会告诉你哪个进程被杀了,它的虚拟内存和物理内存占用是多少,以及当时的系统内存状态。这是排查内存泄漏问题的宝贵线索。

最新文章

随机文章