有时候,我们会碰到程序正常运行了一段时间后有个进程挂掉了,正常情况下进程不会主动挂掉,这种情况有可能是运行时某段时间内存占用过大,系统内存不足导致触发了Linux操作系统OOM killer机制,将运行中的进程杀掉了。

一、Linux内核OOM killer机制

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的那个进程就是那个最占用内存的进程。

【0】什么时候触发?

内核在触发OOM机制时会调用到 out_of_memory() 函数,此函数的调用顺序如下:

以上函数 __alloc_pages_may_oom() 在调用之前会先判断 oom_killer_disabled 的值,如果有值,则不会触发OOM机制;

布尔型变量 oom_killer_disabled 定义在文件mm/page_alloc.c中,并没有提供外部接口更改此值,但是在内核中此值默认为 0 ,表示打开OOM-kill。

Linux中内存都是以页的形式管理的,所以不管是怎么申请内存,都会调用 alloc_page() 函数,最终调用到函数 out_of_memory() ,触发OOM机制。

【1】内核监测到系统内存不足时,该函数被触发执行:

【2】选择一个“最坏的”进程

【3】杀掉进程

二、查看系统日志方法:

运行 egrep-i-r'killed process'/var/log 命令,结果如下:

也可运行 dmesg 命令,结果如下:

显示可读时间的话可用 dmesg-T 查看:

三、附加代码

下面附加两个函数是 select_bad_process() 函数的实现细节,可选看。

最后,简单分析一下你的进程被Linux杀掉几个可能的原因:一种是内存泄露;一种是你的进程所需要的内存资源太大,系统无法满足,应该在设计时对进程需要的资源有个最大限制,不能让他无限增长;当然,也不一定全是你的问题,也有可能是同一主机的其他进程占用资源过多,但是Linux OOM选择“最坏“进程杀掉的算法是很简单粗暴的,就选中你的进程杀掉,也是有可能的。

相关文章