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 OOM-killer机制(杀掉进程,释放内存)相关推荐

  1. Linux内核OOM killer机制

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

  2. linux内核oom,linux OOM killer分析

    基本概念 Linux 内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀 ...

  3. 红帽linux杀进程,weblogic进程无故被kill,redhat oom killer机制

    ./startWebLogic.sh: line 74: 30374 已杀死 ${JAVA_HOME}/bin/java ${JAVA_VM} ${MEM_ARGS} ${JAVA_OPTIONS} ...

  4. linux内核killler,Linux 的 OOM Killer 机制分析

    按需分配物理页面 很多情况下,一个进程会申请一块很大的内存,但只是用到其中的一小部分.为了避免内存的浪费,在分配页面时,Linux 采用的是按需分配物理页面的方式.譬如说,某个进程调用malloc() ...

  5. (转载)Linux OOM Killer个人总结

    Linux下面有个特性叫OOM killer(Out Of Memory killer),这个东西会在系统内存耗尽的情况下跳出来,选择性的干掉一些进程以求释放一些内存.典型的情况是:某天机器突然登不上 ...

  6. Linux 下清理系统缓存并释放内存

    当在Linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作为caching 因此我们很有必要手动清理系统缓存释放内存. 我们在清理缓存前应该先 sync下 因为 ...

  7. Linux OOM Killer

    如何配置 Linux 内存不足终止程序 本文介绍了 Linux 内存不足 (OOM) 终止程序以及如何查明该程序终止特定进程的原因.文中还介绍了配置 OOM 终止程序的方法,以便更好地适应各种不同环境 ...

  8. 查看linux每个进程占用内存多少,Linux下如何查看哪个进程占用内存多?

    1.top top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器 可以直接使用top命令后,查看%MEM的内容.可以选择按进程查看或者 ...

  9. linux跑程序占用缓存过多释放内存echo 3 > /proc/sys/vm/drop_caches

    在跑pytorch时出现了占用内存过多的问题,当然这个问题可以通过调小num_workers解决,不过还有手动解决办法就是释放内存,命令如下: echo 3 > /proc/sys/vm/dro ...

  10. linux 进程 释放内存,Linux 释放内存方法和原理

    今天惊愕地发现,主节点上8G内存被不知道什么进程吃掉了整整6G有余,正常的计算快要维持不下去了,遂处理之. 先看看内存使用状况 [root@node1 ~]# free -m total used f ...

最新文章

  1. php传递JSON数据
  2. UOJ #592. 投放点的选择
  3. oracle11g基目录和主目录,Red Hat Enterprise Linux4.0 安装oracle11g
  4. java中子线程与主线程通信_Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息...
  5. 数据可视化组件Grafana详细解读--在Docker上安装Grafana管理平台
  6. 大数据学习笔记25:MR案例——自定义输入输出格式处理个人成绩
  7. nginx基础概念(100%)之lingering_close
  8. git钩子放服务器_Git代码自动化部署、Hook、钩子
  9. 【离散数学】集合论 第三章 集合与关系(4) 集合的归纳定义、归纳证明、数学归纳法第一/二原理
  10. python货币转换代码_python将人民币转换大写的脚本代码 | 学步园
  11. E24系列电阻 阻值表
  12. LG android TV 蓝牙,LG TV Plus
  13. python画图如何调整图例位置_python中图例的位置怎么手动调整
  14. 决战大数据(升级版):大数据的关键思考 - 电子书下载(高清版PDF格式+EPUB格式)...
  15. 优衣库真的是一家技术驱动型公司?
  16. Objective-C Category 的实现原理
  17. ios13 微信提示音插件_iOS13免越狱修改微信提示音教程 iPhoneXS-11修改微信提示音教程...
  18. Android 开发-创建app
  19. Android神笔之Paint
  20. Python爬虫:js的btoa和atob和pythonBase64编码解码比对分析

热门文章

  1. 机器学习实战-回归算法-18
  2. 使用PYTHON统计项目代码行数
  3. js/jquery遇到的坑总结
  4. Linux系统中文件^M乱码解决
  5. elasticsearch索引和映射
  6. 如何用chrome查看post get及返回的数据
  7. 在IntelliJ IDEA中添加repository模板
  8. 记录下UIButton的图文妙用和子控件的优先显示
  9. 支付接口 随机串 时间戳 防钓鱼效验方式
  10. UINavigationbar的背景修改方法集合