Linux内核OOM机制的详细分析
Linux 内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀掉。典型的情况是:某天一台机器突然ssh远程登录不了,但能ping通,说明不是网络的故障,原因是sshd进程被OOM killer杀掉了(多次遇到这样的假死状况)。重启机器后查看系统日志/var/log/messages会发现Out of Memory: Kill process 1865(sshd)类似的错误信息。
防止重要的系统进程触发(OOM)机制而被杀死:可以设置参数/proc/PID/oom_adj为-17,可临时关闭linux内核的OOM机制。内核会通过特定的算法给每个进程计算一个分数来决定杀哪个进程,每个进程的oom分数可以/proc/PID/oom_score中找到。我们运维过程中保护的一般是sshd和一些管理agent。
保护某个进程不被内核杀掉可以这样操作:
点击(此处)折叠或打开
echo -17 > /proc/$PID/oom_adj
如何防止sshd被杀,可以这样操作:
点击(此处)折叠或打开
pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17 > /proc/$PID/oom_adj;done
可以在计划任务里加入这样一条定时任务,就更安全了:
点击(此处)折叠或打开
#/etc/cron.d/oom_disable
*/1**** root pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17 > /proc/$PID/oom_adj;done
为了避免重启失效,可以写入/etc/rc.d/rc.local
点击(此处)折叠或打开
echo -17 > /proc/$(pidof sshd)/oom_adj
至于为什么用-17而不用其他数值(默认值为0),这个是由linux内核定义的,查看内核源码可知:
以linux-3.3.6版本的kernel源码为例,路径为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机制
点击(此处)折叠或打开
vm.panic_on_oom = 1 //1表示关闭,默认为0表示开启OOM
# sysctl -p
为了验证OOM机制的效果,我们不妨做个测试。
首先看看我系统现有内存大小,没错96G多,物理上还要比查看的值大一些。

再看看目前进程最大的有哪些,top查看,我目前只跑了两个java程序的进程,分别4.6G,再往后redis进程吃了21m,iscsi服务占了32m,gdm占了25m,其它的进程都是几M而已。

现在我自己用C写一个叫bigmem程序,我指定该程序分配内存85G
点击(此处)折叠或打开
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define PAGE_SZ (1<<12)
- int main() {
- int i;
- int gb = 85; //以GB为单位分配内存大小
- for (i = 0; i < ((unsigned long)gb<<30)/PAGE_SZ ; ++i) {
- void *m = malloc(PAGE_SZ);
- if (!m)
- break;
- memset(m, 0, 1);
- }
- printf("allocated %lu MB\n", ((unsigned long)i*PAGE_SZ)>>20);
- getchar();
- return 0;
- }
呵呵,效果明显,然后执行后再用top查看,排在第一位的是我的bigmem,RES是物理内存,已经吃满了85G。

继续观察,当bigmem稳定保持在85G一会后,内核会自动将其进程kill掉,增长的过程中没有被杀,如果不希望被杀可以执行
点击(此处)折叠或打开
pgrep -f "bigmem" | while read PID; do echo -17 > /proc/$PID/oom_adj;done
执行以上命令前后,明显会对比出效果,就可以体会到内核OOM机制的实际作用了。
如果你觉得写C代码麻烦,我告诉大家另外一个最简单的测试触发OOM的方法,可以把某个进程的oom_adj设置到15(最大值),最容易触发。然后执行以下命令:
点击(此处)折叠或打开
- echo f > /proc/sysrq-trigger // 'f' - Will call oom_kill to kill a memory hog process.
以下我来触发mysqld的OOM看看:
需要注意的是这个测试,只是模拟OOM,不会真正杀掉进程
点击(此处)折叠或打开
- ps -ef | grep mysqld | grep -v grep
查看mysql进程,发现依然存在
注意:
1.Kernel-2.6.26之前版本的oomkiller算法不够精确,RHEL 6.x版本的2.6.32可以解决这个问题。
2.子进程会继承父进程的oom_adj。
3.OOM不适合于解决内存泄漏(Memory leak)的问题。
4.有时free查看还有充足的内存,但还是会触发OOM,是因为该进程可能占用了特殊的内存地址空间。
Linux内核OOM机制的详细分析的更多相关文章
- Linux内核OOM机制的详细分析(转)
Linux 内核 有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了 防止内存耗尽而内核会把该进程杀掉.典 ...
- Linux内核OOM机制的详细分析【转】
本文转载自:http://blog.csdn.net/liukuan73/article/details/43238623 Linux内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没 ...
- Linux内核OOM机制的理解【转】
本文转载自:http://blog.csdn.net/zhoutimo/article/details/52024487 What(什么是OOM): Linux下面有个特性叫OOM killer(Ou ...
- armv8(aarch64)linux内核中flush_dcache_all函数详细分析【转】
转自:http://blog.csdn.net/qianlong4526888/article/details/12062809 版权声明:本文为博主原创文章,未经博主允许不得转载. /* * __ ...
- armv8(aarch64)linux内核中flush_dcache_all函数详细分析
/* * __flush_dcache_all() * Flush the wholeD-cache. * Corrupted registers: x0-x7, x9-x11 */ ENTRY( ...
- Linux内核OOM killer机制
程序运行了一段时间,有个进程挂掉了,正常情况下进程不会主动挂掉,简单分析后认为可能是运行时某段时间内存占用过大,系统内存不足导致触发了Linux操作系统OOM killer机制,将运行中的进程杀掉了. ...
- Linux内核同步机制--转发自蜗窝科技
Linux内核同步机制之(一):原子操作 http://www.wowotech.net/linux_kenrel/atomic.html 一.源由 我们的程序逻辑经常遇到这样的操作序列: 1.读一个 ...
- Linux内核同步机制
http://blog.csdn.net/bullbat/article/details/7376424 Linux内核同步控制方法有很多,信号量.锁.原子量.RCU等等,不同的实现方法应用于不同的环 ...
- 浅析Linux内核同步机制
非常早之前就接触过同步这个概念了,可是一直都非常模糊.没有深入地学习了解过,最近有时间了,就花时间研习了一下<linux内核标准教程>和<深入linux设备驱动程序内核机制>这 ...
随机推荐
- Spring MVC Controller中GET方式传过来的中文参数会乱码的问题
Spring MVC controller 这样写法通常意味着访问该请求,GET和POST请求都行,可是经常会遇到,如果碰到参数是中文的,post请求可以,get请求过来就是乱码.如果强行对参数进行了 ...
- oracle pl/sql的操作大全
--删除该用户及下面的所有关联 DROP USER fspdrs CASCADE; --创建一个用户 create user fspdrs identified " default tabl ...
- 【转】M0,M1,M2,M3,M4基本概念
在金融学中的M1,M2,M3,M4都是货币层次的划分M0= 流通中的现金;M1=M0+ 个人信用卡循环信用额度+ 银行借记卡活期存款+ 银行承兑汇票余额+ 企业可开列支票活期存款;M2=M1+ 个人非 ...
- 压力测试工具siege的用法
Siege是linux下的一个web系统的压力测试工具,支持多链接,支持get和post请求,可以对web系统进行多并发下持续请求的压力测试. 安装 Siege 01 02 03 04 #wget h ...
- 让Dock自动 显示/隐藏 不再有延迟
Safari 5.2 Mac OS X 10.7.2 <ignore_js_op> 可能很多朋友使用Mac的时候都会选择将Dock隐藏(可以在系统偏好设置-Dock中选择),等到使用的时候 ...
- 关于HTML代码的转义
笔记: 1.在通过jsonp方式传输HTML代码的时候,为了防止代码中的一些字符影响json的语法,需要对HTML代码进行转义. 2.转义的时候可以只转义特殊字符(引号之类的),也可以把所有字符(中文 ...
- C语言宏定义取得两数的最大值和最小值
/*本程序时为了验证用宏来做 * 两个数的大小比较的写法*/#include<stdio.h>#define MAX(x,y) ((x)<(y)?(y):(x))#define MI ...
- Python试卷
3.写一个函数,计算一个给定的日期是该年的第几天. def getday(self,y=None,m=None,d=None): date = datetime(y,m,d) days = date. ...
- PID控制器的数字实现及C语法讲解
PID控制器的数字实现及C语法讲解 概述 为方便学习与交流,根据自己的理解与经验写了这份教程,有错误之处请各位读者予以指出,具体包含以下三部分内容: (1) PID数字化的推导过程(实质:微积分的近 ...
- 十五、mysql 分区之 分区管理
1.mysql分区处理分区字段NULL值的方式 1.range分区null被当作最小值处理 2.list分区null值必须被枚举出来,否则将出错 3.hash/key分区 null值当作0处理 2.R ...