您的位置首页>企业动态>

linux内核oom机制分析

导读 大家好,我是极客范的本期栏目编辑小友,现在为大家讲解linux内核oom机制分析问题。Linux内核有一个机制叫做OOM killer(Out-Of-Memory

音频解说

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解linux内核oom机制分析问题。

Linux内核有一个机制叫做OOM killer(Out-Of-Memory killer),它监控那些占用过多内存的进程,尤其是那些瞬间消耗大量内存的进程,内核会为了防止内存耗尽而杀死进程。典型情况:有一天,一台机器突然无法通过ssh远程登录,但可以ping通,说明不是网络故障,因为ssh进程被OOM杀手杀死了(这样的假死是多次遇到的)。重新启动机器后查看系统日志/var/log/messages,会发现类似的错误信息如内存不足:kill process 1865 (sshd)。

防止重要的系统进程触发(oom)机制被扼杀:可以将参数/proc/PID/oom_adj设置为-17,暂时关闭linux内核的OOM机制。内核将通过特定的算法为每个进程计算一个分数,以决定杀死哪个进程。每个流程的oom分数可以在/proc/PID/oom_score中找到。在操作和维护过程中,我们一般会保护sshd和一些管理代理。

要保护进程不被内核杀死,您可以这样做:

echo-17 ”/proc/$ PID/oom _ adj

如何防止sshd被杀死,可以通过以下方式完成:

pgrep -f"/usr/sbin/sshd"|在读取PID时;do echo-17 ”/proc/$ PID/oom _ adj;完成的

将这样的计划任务添加到计划任务中更安全:

#/etc/cron.d/oom_disable

*/1****根pgrep -f"/usr/sbin/sshd"|在读取PID时;do echo-17 ”/proc/$ PID/oom _ adj;完成的

为了避免重启失败,可以写/etc /etc/rc.d/rc.local

echo-17 ”/proc/

至于为什么用-17代替其他值(默认值为0),这是linux内核定义的,从内核源代码可以看到:

以linux-3.3.6版本的内核源代码为例,路径为Linux-3 . 6 . 6/include/Linux/oom . h,阅读内核源代码可知oom_adj的可调值为15到-16,其中15为最大值-16为最小值,-17表示禁止OOM。Oom_score计算为2的n次方,其中n是进程的oom_adj值,因此oom_score的分数越高,越会被内核优先杀死。

当然,OOM机制也可以通过修改内核参数来禁止。

# sysctl -w vm .恐慌_on_oom=1

Vm .恐慌_on_oom=1 //1表示关闭,默认值为0表示打开oom。

# sysctl -p

为了验证OOM机制的效果,我们不妨做一个测试。

首先,看看我的系统现有的内存大小,超过96G,物理上比检查的值大。

看看目前最大的流程。从顶视图来看,我目前只运行了两个java程序,分别是4.6G。未来,redis进程ate 21m万,iscsi服务占3200万,gdm占2500万,其他进程只有几米。

现在我用C语言写了一个叫bigmem的程序,我指定这个程序分配85G内存。

#包括《stdio.h》

#包括《stdlib.h》

#包括《string.h》

#定义PAGE _ SZ(1)《12》

int main(){ 0

int I;

int gb=85//以GB为单位分配内存大小。

for(I=0;I 《(无符号长)GB》《30)/PAGE _ SZ;I){ 0

void * m=malloc(PAGE _ SZ);

if(!m)

打破;

memset(m,0,1);

}

printf("已分配%lu MB\n",((无符号长)I * PAGE _ SZ)】20);

getchar();

返回0;

}

效果明显,执行后再与高层核对。我的bigmem排名第一,RES是物理内存,已经吃过85G了。

继续观察,当bigmem在85G保持稳定一段时间后,内核会自动杀死它的进程,但在成长过程中并没有被杀死。如果你不想被杀死,你可以执行它。

阅读PID时,单击(此处)折叠或打开pgrep-f“big mem”|;do echo-17 ”/proc/$ PID/oom _ adj;完成的

执行上述命令前后,效果会有明显的对比,可以实现内核OOM机制的实际功能。

如果你觉得写C代码很麻烦,我会告诉你另一个最简单的测试和触发OOM的方法。您可以将某个进程的oom_adj设置为15(最大值),这是最容易触发的。然后执行以下命令:

echo f ”/proc/sysrq-trigger/“f”-将调用oom_kill来杀死内存占用进程。

让我触发mysqld的OOM看看:

需要注意的是,这个测试只是模拟OOM,并不会真正扼杀这个过程。

ps -ef | grep mysqld | grep -v grep

纵观mysql进程,它依然存在。

注意:

1.1之前的oomkiller算法。内核-2.6.26不够准确。RHEL 6.x的2.6.32可以解决这个问题。

2.子进程将继承父进程的oom_adj。

3.OOM不适合解决内存泄漏的问题。

4.有时候有足够的内存可以自由查看,但是OOM仍然会被触发,因为进程可能会占用一个特殊的内存地址空间。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。