【转载】Linux内核OOM机制的详细分析

Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是瞬间占用内存很快的进程,然后防止内存耗尽而自动把该进程杀掉。典型的情况是:某天机器突然登不上了,能ping通,但是ssh死活连不了。原因是sshd进程被OOM killer杀掉了(多次遇到这样的假...显示全部

Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是瞬间占用内存很快的进程,然后防止内存耗尽而自动把该进程杀掉。典型的情况是:某天机器突然登不上了,能ping通,但是ssh死活连不了。原因是sshd进程被OOM killer杀掉了(多次遇到这样的假死状况)。重启机器后查看系统日志会发现Out of Memory: Killed process ×××的错误提示。


防止关键进程被系统因内紧张(OOM)被杀死:设置参数/proc/pid/oom_adj为-17,可禁止被系统内核杀掉。内核会通过特定的算法给每个进程计算一个分数来决定杀哪个进程,每个进程的oom分数可以/proc/pid/oos_score中找到。我们运维过程中保护的一般是sshd和一些管理agent。


保护某个进程不被内核杀掉可以这样操作:



1

echo -17 > /proc/$PID/oom_adj





如何防止sshd被杀,可以这样操作:





1

pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17 > /proc/$PID/oom_adj;done



可以在计划任务里加入这样一条定时任务,就更安全了:







1

2

#/etc/cron.d/oom_disable
*/1**** root pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17> /proc/$PID/oom_adj;done



至于为什么用-17而不用其他数值(默认值为0,即默认使用OOM机制),这个不是我定义的,而是linux内核定义的,以下是代码可知:

文件是以linux-3.3.6版本的kernel源码为例,路径为linux-3.6.6/include/linux/oom.h


有些朋友可能没遇到过,到底真的存不存在OOM机制呢?不妨测试给大家看看吧。

首先看看我系统现有内存大小,没错96G多,物理上还要多一些,不要羡慕,呵呵


再看看目前进程最大的有哪些,top查看,我目前只跑了两个java程序的进程,分别4.6G,再往后redis进程吃了21m,iscsi服务占了32m,gdm占了25m,其它的进程都是几M而已了。

现在我自己用C写一个叫bigmem程序,我指定该程序分配内存85G,呵呵,效果明显,然后执行后再用top查看,排在第一位的是我的bigmem,RES是物理内存,已经吃满了85G。

继续观察,当bigmem稳定保持在85G一会后,内核会自动将其进程kill掉,增长的过程中没有被杀,如果不希望被杀可以执行



1

pgrep -f "bigmem" | while read PID; do echo -17 > /proc/$PID/oom_adj;done



执行以上命令前后,明显会对比出效果,就可以体会到内核OOM机制的实际作用了。


PS:kernel-2.6.26之前版本的oomkiller算法不够精确,RHEL 6.x版本的2.6.32可以解决这个问题。

祝大家玩的开心,晚安!

收起
参与2

返回yulu4314的回答

yulu4314yulu4314技术支持长春

谢谢分享。内容值得阅读

系统集成 · 2022-08-31
浏览315

回答者

yulu4314
yulu4314111842
技术支持长春
擅长领域: 服务器存储数据库

yulu4314 最近回答过的问题

回答状态

  • 发布时间:2022-08-31
  • 关注会员:1 人
  • 回答浏览:315
  • X社区推广