OOM Killer
Linux 内核有个 OOM (Out of Memory) Killer 的机制,可以在系统内存不足的时候,通过主动杀死一些进程来释放更多的内存空间。
很多时候,可以 ping 通一台服务器,但无法 ssh 上去,因为 sshd 被 OOM Killer 杀掉了。ping 能 ping 通,是因为处在内核态协议栈还能工作,发出回送报文。sshd 则因为是用户态进程,直接被干掉了。
OOM Killer 工作流程
OOM Killer 的完整工作流程如下:
graph TD
A[系统内存不足] --> B{是否触发 OOM?}
B -->|是| C[遍历所有进程]
B -->|否| Z[继续正常运行]
C --> D[计算每个进程的 oom_score]
D --> E[应用 oom_score_adj 调整]
E --> F[选择分数最高的进程]
F --> G{是否启用 OOM Killer?}
G -->|否| H[系统挂起/panic]
G -->|是| I[发送 SIGKILL 信号]
I --> J[进程被杀死]
J --> K[释放内存资源]
K --> Z
关键机制
oom_score
每个进程都有一个 oom_score 值,范围是 0 到 1000,分数越高越容易被 OOM Killer 选中。可以通过 /proc/PID/oom_score 查看。
oom_score 的计算主要考虑以下因素:
- 进程占用的内存大小:包括虚拟内存、物理内存、swap 空间等
- 进程的运行时间:运行时间长的进程分数较低
- 进程的优先级:nice 值会影响分数
- 进程的 root 权限:root 进程会有一定的保护
- 是否直接访问硬件:直接访问硬件的进程分数会降低
oom_score_adj
oom_score_adj 是调整进程 oom_score 的接口,范围是 -1000 到 1000。可以通过 /proc/PID/oom_score_adj 进行设置。
- -1000:完全禁止 OOM Killer 杀死该进程(相当于旧的 oom_adj = -17)
- 0:默认值,不调整
- 1000:极大增加被杀死的概率
旧的 oom_adj 接口(范围 -17 到 15)已被废弃,新代码应使用 oom_score_adj。
vm.overcommit_memory
vm.overcommit_memory 参数控制内核的内存过度分配策略,位于 /proc/sys/vm/overcommit_memory:
- 0:启发式过度分配(默认值),内核会根据实际情况决定是否允许过度分配
- 1:总是允许过度分配,可能导致 OOM
- 2:严格过度分配控制,不允许过度分配超过 swap + 可配置的 RAM 比例
控制 OOM Killer
关闭再打开 OOM Killer
1 | |
保护特定进程
可以通过设置 oom_score_adj 为 -1000 来强制内核不得杀死某个进程:
1 | |
或者针对单个进程:
1 | |
cgroup 与 OOM Killer
在容器化环境中,cgroup 提供了更精细的 OOM 控制机制。
cgroup v1
在 cgroup v1 中,memory subsystem 提供了以下控制:
memory.limit_in_bytes:设置内存限制memory.oom_control:控制 OOM 行为- 设置为 0 时禁用该 cgroup 的 OOM Killer
- 设置为 1 时启用 OOM Killer
cgroup v2
在 cgroup v2 中,OOM 控制更加统一:
memory.max:设置内存限制memory.oom.group:控制是否杀死整个进程组- 设置为 0 时只杀死触发 OOM 的进程
- 设置为 1 时杀死整个 cgroup 中的所有进程
排查 OOM 问题
查看 OOM 日志
1 | |
典型的 OOM 日志如下:
1 | |
监控内存使用
1 | |
预防措施
- 合理设置 swap:适当的 swap 空间可以缓解内存压力
- 监控内存使用:使用监控工具及时发现内存异常
- 优化程序:减少内存泄漏和不必要的内存占用
- 设置合理的 limits:使用 ulimit 或 cgroup 限制进程内存
- 配置 OOM 保护:对关键进程设置
oom_score_adj = -1000
参考文档:
- 关于OOM-killer
- 这里有一篇《OOM Killer》讨论它的工作细节。
- Linux 下 OOM Killer 机制的详解
- Linux内核OOM机制的详细分析
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.



