01
概述
在工作中,经常会遇到一些进程莫名其妙的退出了,无错误日志,无core文件,特别是在虚拟机环境中,应用进程申请占用内存比较多的情况下,这种现象更为常见,这或许与oom killer有关。
02
什么是oom killer
oom killer是linux内核设计的一种机制,当系统内存不足时,会根据一定的算法杀掉相应的进程,以满足内存申请的需要,保证系统继续运行。
03
为什么要oom killer
当应用进程申请一块很大的内存时,系统将返回虚拟内存地址,同时为相应的虚拟内存创建内存映射,并将它放入到页表中,但这时系统并不一定会分配相应大小的物理内存给该进程使用。当进程真正访问到这段内存时才会分配物理内存,这就是linux采用的按需(延时)分配物理页面的方式,这种按需分配物理页面的方式,可以很大程度节省物理内存的使用。同时,linux为了用户有更好的体验感,linux是允许进程申请内存大于实际可用内存(memory overcommit),在大多数情况下,memory overcommit是安全的,因为进程申请的内存并不能真正使用到这些内存,但当进程实际使用到这些内存,怎么办?就会发生内存不足的情况,这时oom killer就出来工作了,根据算法杀死某个进程,来释放相应的内存。
04
如何选择要杀掉的进程
当发生内存不足时,内核是如何选择要杀掉的进程的呢?内核有一套算法,总体上来说,内核根据进程的系统得分和用户设置的分数,分数越高,被杀掉的几率也就越大。详见下图:
05
OOM相关的内核参数
➢ 参数overcommit_memory
由于oom killer与memory overcommit密切相关,其实我们可以调整memory overcommit参数来控制oom killer发生。overcommit memory有三个选项值;如下:
overcommit_memory---0:默认值,轻微的允许,严重的拒绝
overcommit_memory---1:总是允许overcommit
overcommit_memory---2:禁止overcommit
通过echo 2 >/proc/sys/vm/overcommit_memory修改该参数的值,当设置为2时, OOM就永远不会发生。
➢ 参数panic_on_oom---内核遇到OOM时,采用何种方式处理,参照上图。
➢ 参数oom_kill_allocating_task
当参数oom_kill_allocating_task配置为0时,则内核根据score来选择要杀掉的线程,当配置为非0时,则杀掉触发OOM的线程。
注:以上三个参数都位于路径/proc/sys/vm/下
➢ oom_score_adj和oom_score
从上图可以看到,当发生OOM时,需要选择kill对象时,系统计算相应的“得分”值,“得分"越高被kill的几率越大。oom_score参数就是系统计算的得分值,该参数是只读的,不允许用户修改。而参数oom_score_adj是用户可以设置的,当设置为OOM_SCORE_ADJ_MIN(-1000)时,禁止kill该进程;如果设置为OOM_SCORE_ADJ_MAX(1000),则该进程必死无疑。因此oom_score_adj参数范围在【-1000,1000】,数值越大,被kill的几率也就越大。
注:该两个参数与进程相关,位于/proc/xxxx/oom_score,oom_score_adj下
06
问题排查
当发生OOM时,对于应用进程来说那可是“神不知鬼不觉”的进行了,即看不到core文件,又再日志中查不到错误信息。当发生这种情况时,就有可能OOM KILLER了,首先查看系统日志,可以通过以下两种方法:
一:使用dmesg命令,很容易看到“Out of memory"关键字
二:cat /var/log/messages|grep "Out of memory" 也能够查到
例如:下图
图中信息中显示的kill进程号,score,内存信息等。
注意:如果通过上面的命令,也没有相关的日志信息,还有可能内核参数oom_dump_tasks被设置了0,设置为非0,才会有相应的信息输出。可以查看/proc/sys/vm/oom_dump_tasks