Linux下面有个特性叫OOM killer(Out Of Memory killer),这个东西会在系统内存耗尽的情况下跳出来,选择性的干掉一些进程以求释放一些内存。相信广大从事Linux服务端编程的农民工兄弟们或多或少遇到过(人在江湖漂,哪有不挨刀啊)。典型的情况是:某天机器突然登不上了,能ping通,但是ssh死活连不了。原因是sshd进程被OOM killer干掉了(泪流满面)。重启机器后查看系统日志会发现血淋淋的Out of Memory: Killed process ×××、Out of Memory: Killed process 〇〇〇。一篇狼藉,惨不忍睹。

前段时间我就被OOM killer虐过一次。情况是这样的。一个简单的分布式系统,A,B,C等对称的节点分担处理X节点吐出的数据,然后将结果塞到Y节点去。结果负荷一大,ABC处理不过来,数据堆积在内存中,内存耗光,逼得OOM killer出来收拾局面,sshd被干掉,更杯具的是,重启后发现,syslogd也被干掉了,而且是在sshd前面被干掉。想查日志也只能查到一部分。血淋淋的。这也引出了分布式系统设计中的问题:想上面那种设计,要防止ABC中某个节点突然挂掉,然后导致其他节点负荷突然增加紧跟着也挂掉(连锁挂掉)。

回归正题,Linux下面的OOM killer到底是什么样一个机制呢,它在什么时候会跳出来,又会选择那些进程下手呢。

什么时候跳出来

先看第一个问题,它什么时候会跳出来。是不是malloc返回NULL的时候跳出来呢?不是的,malloc的manpage里有下面一段话:

By default, Linux follows an  optimistic  memory  allocation  strategy.
This  means  that  when malloc() returns non-NULL there is no guarantee
that the memory really is available.  This is a  really  bad  bug.   In
case  it  turns  out that the system is out of memory, one or more processes
will be killed by the infamous OOM killer.   In  case  Linux  is
employed  under  circumstances where it would be less desirable to suddenly
lose some randomly picked processes, and moreover the kernel version 
is  sufficiently  recent,  one can switch off this overcommitting
behavior using a command like:

# echo 2 > /proc/sys/vm/overcommit_memory

上面一段话告诉我们,Linux中malloc返回非空指针,并不一定意味着指向的内存就是可用的,Linux下允许程序申请比系统可用内存更多的内存,这个特性叫Overcommit。这样做是出于优化系统考虑,因为不是所有的程序申请了内存就立刻使用的,当你使用的时候说不定系统已经回收了一些资源了。不幸的是,当你用到这个Overcommit给你的内存的时候,系统还没有资源的话,OOM killer就跳出来了。

Linux下有3种Overcommit的策略(参考内核文档:vm/overcommit-accounting),可以在/proc/sys/vm/overcommit_memory配置。取0,1和2三个值,默认是0。

0:启发式策略,比较严重的Overcommit将不能得逞,比如你突然申请了128TB的内存。而轻微的Overcommit将被允许。另外,root能Overcommit的值比普通用户要稍微多些。

1:永远允许Overcommit,这种策略适合那些不能承受内存分配失败的应用,比如某些科学计算应用。

2:永远禁止Overcommit,在这个情况下,系统所能分配的内存不会超过swap+RAM*系数(/proc/sys/vm/overcmmit_ratio,默认50%,你可以调整),如果这么多资源已经用光,那么后面任何尝试申请内存的行为都会返回错误,这通常意味着此时没法运行任何新程序。

补充(待考证):在这篇文章:Memory overcommit in Linux中,作者提到,实际上启发策略只有在启用了SMACK或者SELinux模块时才会起作用,其他情况下等于永远允许策略。

跳出来之后选择进程的策略

好了,只要存在Overcommit,就可能会有OOM killer跳出来。那么OOM killer跳出来之后选目标的策略又是什么呢?我们期望的是:没用的且耗内存多的程序被枪。

Linux下这个选择策略也一直在不断的演化。作为用户,我们可以通过设置一些值来影响OOM killer做出决策。Linux下每个进程都有个OOM权重,在/proc/<pid>/oom_adj里面,取值是-17到+15,取值越高,越容易被干掉。

最终OOM killer是通过/proc/<pid>/oom_score这个值来决定哪个进程被干掉的。这个值是系统综合进程的内存消耗量、CPU时间(utime + stime)、存活时间(uptime - start time)和oom_adj计算出的,消耗内存越多分越高,存活时间越长分越低。总之,总的策略是:损失最少的工作,释放最大的内存同时不伤及无辜的用了很大内存的进程,并且杀掉的进程数尽量少。

另外,Linux在计算进程的内存消耗的时候,会将子进程所耗内存的一半同时算到父进程中。这样,那些子进程比较多的进程就要小心了。

当然还有其他的策略,大家可以参考文章:Taming the OOM killer和When Linux Runs Out of Memory。

Linux开发心得总结5 - Linux下OOM Killer机制详解相关推荐

  1. linux网卡驱动离线安装_Linux下安装网卡驱动程序详解 | 吴文辉博客

    我的centos 5.5网卡驱动是r8169,而官方网站出来了最新驱动是r8168,这让我感觉很怪异,r8169这些数据难道不代表驱动版本,还是r8169不是官方开发的.以防万一换了在说.下面将以我的 ...

  2. linux 强制类型转换,C++ 新标准下的强制类型转换详解

    使用标准C++的类型转换符:static_cast.dynamic_cast.reinterpret_cast和const_cast. static_cast 用法:static_cast (expr ...

  3. Linux内核OOM killer机制

    程序运行了一段时间,有个进程挂掉了,正常情况下进程不会主动挂掉,简单分析后认为可能是运行时某段时间内存占用过大,系统内存不足导致触发了Linux操作系统OOM killer机制,将运行中的进程杀掉了. ...

  4. Linux OOM机制详解

    Linux OOM机制说明 在工作过程中,你可能会遇到过这种情况,程序在运行一段时间之后突然挂掉,在你保证程序在正常情况下不会挂掉的情况下,程序挂掉的原因可能是在你的程序运行过程中,有一段时间你的程序 ...

  5. linux下sort命令使用详解---linux将文本文件内容加以排序命令

    转载自:http://www.cnblogs.com/hitwtx/archive/2011/12/03/2274592.html linux下sort命令使用详解---linux将文本文件内容加以排 ...

  6. Linux下的awk用法详解

    Linux下的awk用法详解 一.awk介绍 二.awk的语法 三.awk常见用法 四.awk其他用法 五.awk语言特性 一.awk介绍 1.AWK 是一种处理文本文件的语言,是一个强大的文本分析工 ...

  7. linux输入一个用户看是否在工作,linux下的用户管理详解

    linux下的用户管理详解 useradd 命令详解 添加用户 想要对linux下面的帐号了解的话首先必须要了解的4个配置文件[root@localhost /]# cat /etc/passwd 首 ...

  8. Linux下find命令用法详解

    Linux下find命令用法详解 学神VIP烟火 学神IT教育:XueGod-IT 最负责任的线上直播教育平台 本文作者为VIP学员 烟火 第一部分:根据文件名查找 1.在当前目录查找名称为test的 ...

  9. linux中which命令详解,Linux下which命令使用详解(转)

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. locate 配合数据库查看文件位置. f ...

  10. Linux下Grub命令配置详解

    grub(Grand Unified Boot Loader)启动引导器 与grub相似软件比较 BM:安装多操作系统软件,必须把两个操作系统安装在主分区,硬盘最多可以分4个主分区. LILO:以前l ...

最新文章

  1. js进阶 13-6 jquery动画效果相关常用函数有哪些
  2. 访问一个HTTPS的网站的大致流程
  3. 多继承中构造器和析构器的调用顺序
  4. c语言实现配置文件的读写
  5. repcached配置与简单測试
  6. linux pcre静态编译,Linux下,Nginx部署静态网站
  7. 账号管理工具_新媒体账号管理工具,自媒体运营神器,管理多个账号很简单
  8. 英语总结系列(二):爽约Pauel叔十五天
  9. Magento开发文档(二):Magento配置
  10. 使用Eclipse开发Java EE应用
  11. PAIP.MYSQL 1045 Access denied for user 'XXXX'@'loca 的解决.txt
  12. 语料库资源————(一)
  13. u盘linux反应好慢,识别U盘很缓慢怎么办的八种解决方法
  14. 【Adobe】Photoshop :Mac 系统 Photoshop 软件更换许可指引
  15. 机器学习和人工智能的关系是什么?
  16. 对比MIUI7和Flyme4.5 期待神秘的Flyme5
  17. 双重检查锁为什么要使用volatile字段?
  18. Miniconda在服务器上的安装与使用
  19. 232层3D闪存芯片来了:单片容量2TB,传输速度提高50%
  20. 大数据时代的日本“化石”企业家

热门文章

  1. win7建WLAN热点
  2. QT3D场景的快速绘制
  3. Java8 jdk1.8新特性
  4. Ubuntu上无法登录网页版本微信的解决方案
  5. SAT考试填空习题(一)及答案
  6. 【ReID】Pyramidal Person Re-IDentification via Multi-Loss Dynamic Training
  7. 去掉UISearchBar自带的的边框背景
  8. 使用Rasterio读取栅格数据
  9. 读取HDF或者NetCDF格式的栅格数据
  10. PyCharm下载和安装教程