What(什么是OOM):
Linux下面有个非常特别的机制叫OOM killer(Out Of Memory killer),这个有趣的家伙会在系统内存耗尽的情况下跳出来,选择性的干掉一些进程以求释放一些内存。默认具体的记录日志是在/var/log/messages中,如果出现了Out of memory字样,说明系统曾经出现过OOM!
When(什么时候出现):
linux下允许程序申请比系统可用内存更多的内存,这个特性叫Overcommit。这样做是出于优化系统考虑,因为不是所有的程序申请了内存就立刻使用的,当使用的时候说不定系统已经回收了一些资源了。不幸的是,当用到这个Overcommit给的内存的时候,系统还没有资源的话,OOM killer就跳出来了。
参数/proc/sys/vm/overcommit_memory可以控制进程对内存过量使用的应对策略
1.overcommit_memory=0,这是缺省值,表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
2.overcommit_memory=1,表示内核允许分配所有的物理内存,而不会检查当前的内存状态如何,换句话说就是来者不拒。这种策略适合那些不能承受内存分配失败的应用,比如某些科学计算应用。
3.overcommit_memory=2,表示系统所能分配的内存不会超过swap+RAM*系数(/proc/sys/vm /overcmmit_ratio,默认50%,你可以调整),如果这么多资源已经用光,那么后面任何尝试申请内存的行为都会返回错误,这通常意味着此时没法运行任何新程序。
How(系统会怎么样):
当然,如果触发了OOM机制,系统会杀掉某些进程,那么什么进程会被处理掉呢?kernel提供给用户态的/proc下的一些参数:
1./proc/[pid]/oom_adj,该pid进程被oom killer杀掉的权重,一般介于 [-17,15](具体具体权重的范围需要查看内核确认)之间,越高的权重,意味着更可能被oom killer选中,-17表示禁止被kill掉。
通过2个步骤可以确认,具体权重的范围:
①uname -a查看Linux内核版本
②进入/usr/src/kernels/内核版本/include/linux/oom.h确认具体的权重范围
2./proc/[pid]/oom_score,当前该pid进程的被kill的分数,越高的分数意味着越可能被kill,这个数值是根据oom_adj运算(2ⁿ,n就是oom_adj的值)后的结果,本身oom_score是不能修改值。
下面的流程图是out_of_memory的调用关系,触发OOM时会调用__out_of_memory函数。
__out_of_memory函数主要做了两件事:
1.调用select_bad_process函数选择一个最优的进程杀掉
2.根据选择的最优的进程,调用函数oom_kill_process,杀掉该进程。
So(我们能做什么):
1.保护我们重要的进程,避免被处理掉
实例:
ps -ef|grep GameServer(获得重要进程的PID)
echo -17 > /proc/PID/oom_score_adj(输入-17,禁止被OOM机制处理)
2.开启OOM较为的保险机制
echo “vm.panic_on_oom=2” >> /etc/sysctl.conf
systcl -p