Linux 内核 OOM killer 机制
有时候,我们会碰到程序正常运行了一段时间后有个进程挂掉了,正常情况下进程不会主动挂掉,这种情况有可能是运行时某段时间内存占用过大,系统内存不足导致触发了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选择“最坏“进程杀掉的算法是很简单粗暴的,就选中你的进程杀掉,也是有可能的。