暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Linux之OOM简述

原创 何权林 2020-05-19
7351

环境:SUSE Linux Enterprise Server11

前言:
在我们维护Linux操作系统的时候,有时会遇到应用被无辜被Kill掉,查看系统日志会发现类似如下信息,
…host_name kernel:[…] app_name invoked oom-killer:…

一、什么是OOM?
OOM:out of memory,内存溢出。
oom_killer是Linux自我保护的方式,防止内存不足时出现严重问题。
Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是瞬间占用内存很快的进程,然后防止内存耗尽而自动把该进程杀掉。内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory()被触发,然后调用select_bad_process()选择一个”bad”进程杀掉。如何判断和选择一个”bad进程呢?linux选择”bad”进程是通过调用oom_badness(),挑选的算法和想法都很简单很朴实:最bad的那个进程就是那个最占用内存的进程。

二、查看是否发生OOM?
1、grep “oom-killer” /var/log/messages

2、dmesg | grep -i “memory”
注:看到硬件的检测或者断开连接的信息。

三、如何禁用OOM?
方式一:禁止某个进程被oom调用
echo -17 > /proc/pid/oom_adj,-17表示禁止这个进程被OOM掉.

方式二:设置整个系统(内存不足时是否调用OOM)
sysctl -w vm.panic_on_oom=1 (默认为0)
sysctl -p
0,表示内存不足时,执行OOM;(建议值)
1,表示内存不足时,部分情况执行OOM,部分情况直接重启系统;
2,表示内存不足时,直接重启系统。
注:也就是说内存不足,除了OOM就是重启。。。

方式三:系统是否可过量使用内存
参数/proc/sys/vm/overcommit_memory可以控制进程对内存过量使用的应对策略
当overcommit_memory=0,允许进程轻微过量使用内存,但对于大量过载请求则不允许(默认);
当overcommit_memory=1,永远允许进程overcommit;
当overcommit_memory=2,永远禁止overcommit。
注:设置为2后,系统内存可使用量减少,但可调节。如果内存不能超用了,也就不会触发OOM。

四、OOM时,依据什么杀掉进程?
参数:panic_on_oom: 用来控制当内存不足时是否启用OOM
值为0:内存不足时,启动 OOM killer。
值为1:内存不足时,有可能会触发 kernel panic(系统重启),也有可能启动 OOM killer。
值为2:内存不足时,表示强制触发 kernel panic,内核崩溃GG(系统重启)。

参数:oom_kill_allocating_task: 用来决定杀掉哪种进程
值为0:会 kill 掉得分最高的进程。
值为非0:会kill 掉当前申请内存而触发OOM的进程。
当然,一些系统进程(如init)或者被用户设置了oom_score_adj的进程等可不是说杀就杀的。

参数:oom_dump_tasks:用来记录日志
oom_dump_tasks参数可以记录进程标识信息、该进程使用的虚拟内存总量、物理内存、进程的页表信息等。

值为0:关闭打印上述日志。在大型系统中,可能存在上千进程,逐一打印使用内存信息可能会造成性能问题。
值为非0:有三种情况会打印进程内存使用情况。
1、由 OOM 导致 kernel panic 时;
2、没有找到符合条件的进程 kill 时;
3、找到符合条件的进程并 kill 时。

参数:oom_adj、oom_score_adj 和 oom_score:用来控制进程打分(分数越高,就先杀谁)
这三个参数的关联性比较紧密,都和具体的进程相关,位置都是在 /proc/进程PID/ 目录下。

内核会对进程打分(oom_score),主要包括两部分,系统打分和用户打分。系统打分就是根据进程的物理内存消耗量;用户打分就是 oom_score_adj 的值。如果用户指定 oom_score_adj 的值为 -1000,也就是表示禁止 OOM killer 杀死该进程。

用户可以通过调整 oom_score_adj 的值来决定最终 oom_score 的值,oom_score_adj 的取值范围是 -1000~1000,为0时表示用户不调整 oom_score。另外,root进程拥有3%的内存使用特权,因此做最终 oom_score 计算时需要减去这些内存使用量。

oom_adj是一个旧的接口参数,其功能类似oom_score_adj,为了兼容,目前仍然保留这个参数,当操作这个参数的时候,kernel实际上是会换算成oom_score_adj。

五、总结
建议不要关闭OOM,如果系统中是多应用,建议找出重要的进程,单独设定禁用OOM。如果只有一个重要应用,建议从应用层面降低内存消耗。有时因为内存泄漏导致内存溢出,这时只能通过重启应用或者操作系统解决。

其他:
1、子进程会继承父进程的oom_adj。
2、OOM不适合于解决内存泄漏(Memory leak)的问题。
3、有时free查看还有充足的内存,但还是会触发OOM,是因为该进程可能占用了特殊的内存地址空间。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论