首先了解一下什么是oom killer?
简单理解是, Linux内核里出于保护其他资源,不致于让系统立刻崩溃,采取了一种保护进程手段,当linux系统所剩的内存空间不足以满足系统正常运行时,把使用内存异常服务进行kill。

具体而言,oom killer的操作,主要有以下步骤:当系统内存不足的时候,out_of_memory()被触发,然后调用select_bad_process()选择一个”bad”进程杀掉。如何判断和选择一个”bad进程呢?linux选择”bad”进程是通过调用oom_badness(),挑选的算法和想法都很简单很朴实:最bad的那个进程就是那个最占用内存的进程。

参考内核源代码linux/mm/oom_kill.c
https://github.com/torvalds/linux/blob/master/mm/oom_kill.c
https://elixir.free-electrons.com/linux/v2.6.18/source/mm/oom_kill.c

什么时候触发oom_kill.c?
从名称上看就是要发生out_of_memory(),如果检查到内存不足,则触发OOM机制。OOM首先会对系统所有进程(出init和内核线程等特殊进程)进行打分,并选出最bad的进程;然后杀死该进程。

out_of_memory()核心几行代码,主要是:

void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,int order, nodemask_t *nodemask, bool force_kill)
{...p = select_bad_process(&points, totalpages, mpol_mask, force_kill);if (!p) {dump_header(NULL, gfp_mask, order, NULL, mpol_mask);panic("Out of memory and no killable processes...\n");}// kill掉被选中的进程,以释放内存。if (PTR_ERR(p) != -1UL) {oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,nodemask, "Out of memory");killed = 1;}
}

out_of_memory两个核心步骤:
(1)select_bad_process(),选择要kill掉的进程
(2)如果选取成功,则调用oom_kill_process()kill指向的进程,没有的话panic(通常不会走到这个流程,但也有例外,比如,当被选中的进程处于D状态,或者正在被kill)。

步骤一:oom_kill_process
核心源码:

static void __oom_kill_process(struct task_struct *victim, const char *message)
{struct task_struct *p;struct mm_struct *mm;.../* Get a reference to safely compare mm after task_unlock(victim) */mm = victim->mm;.../** We should send SIGKILL before granting access to memory reserves* in order to prevent the OOM victim from depleting the memory* reserves from the user space under its control.*/do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID);mark_oom_victim(victim);pr_err("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB, UID:%u pgtables:%lukB oom_score_adj:%hd\n",message, task_pid_nr(victim), victim->comm, K(mm->total_vm),K(get_mm_counter(mm, MM_ANONPAGES)),K(get_mm_counter(mm, MM_FILEPAGES)),K(get_mm_counter(mm, MM_SHMEMPAGES)),from_kuid(&init_user_ns, task_uid(victim)),mm_pgtables_bytes(mm) >> 10, victim->signal->oom_score_adj);...
}

通过向victim进程发送SIGKILL这个signal(我们平时使用的kill -9命令,就是用的这个signal),将其kill掉,然后该kill事件,会被记录到内核日志中。

步骤二:select_bad_process()计算score?
用select_bad_process()选择badness指数(oom_score)最高的进程,score的值影响因素有很多,内存占用大小、运行时间、权重等。权重越高,分值越高,运行时间越短,分值越高,内存越大,分值越高。
源码:
https://github.com/torvalds/linux/blob/5147da902e0dd162c6254a61e4c57f21b60a9b1c/mm/oom_kill.c

/** Simple selection loop. We choose the process with the highest number of* 'points'. In case scan was aborted, oc->chosen is set to -1.*/
static void select_bad_process(struct oom_control *oc)
{if (is_memcg_oom(oc))mem_cgroup_scan_tasks(oc->memcg, oom_evaluate_task, oc);else {struct task_struct *p;rcu_read_lock();for_each_process(p)if (oom_evaluate_task(p, oc))break;rcu_read_unlock();}oc->chosen_points = oc->chosen_points * 1000 / oc->totalpages;
}

简单分析一下源码:
oc值是刚才out_of_memory中选择要kill的进程,select_bad_process会遍历系统中的所有进程,然后使用oom_evaluate_task(),对各个进程进行评估:

ok 那么还得看一下oom_evaluate_task()的源码,
核心源码:

static int oom_evaluate_task(struct task_struct *task, void *arg)
{struct oom_control *oc = arg;long points;...points = oom_badness(task, oc->totalpages);if (points == LONG_MIN || points < oc->chosen_points)goto next;select:if (oc->chosen)put_task_struct(oc->chosen);get_task_struct(task);oc->chosen = task;oc->chosen_points = points;
next:return 0;...
}

oom_evaluate_task()中,会使用oom_badness()计算某进程badness的点数,点数越高,越容易被kill掉。
(1)如果badness的点数等于LONG_MIN或者badness点数小于之前选择进程的badness点数,则直接跳过该进程,即该进程不会成为被kill掉的对象。
(2)badness的点数大于等于留下进行下一轮比较。直到等到最大的badness,oom_kill_process里kill掉的进程。

badness点数是如何计算的?
源码:

long oom_badness(struct task_struct *p, unsigned long totalpages)
{long points;long adj;if (oom_unkillable_task(p))return LONG_MIN;p = find_lock_task_mm(p);if (!p)return LONG_MIN;/** Do not even consider tasks which are explicitly marked oom* unkillable or have been already oom reaped or the are in* the middle of vfork*/adj = (long)p->signal->oom_score_adj;if (adj == OOM_SCORE_ADJ_MIN ||test_bit(MMF_OOM_SKIP, &p->mm->flags) ||in_vfork(p)) {task_unlock(p);return LONG_MIN;}/** The baseline for the badness score is the proportion of RAM that each* task's rss, pagetable and swap space use.*/points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) +mm_pgtables_bytes(p->mm) / PAGE_SIZE;task_unlock(p);/* Normalize to oom_score_adj units */adj *= totalpages / 1000;points += adj;return points;
}

(1)oom_score
首先介绍一下oom_score,是对某一个task进行的打分,oom_score主要有两部分组成

(2)一部分是用户打分,也就是oom_score_adj。
oom_score_adj,是进程独有的,是可以通过写 /proc/[pid]/oom_score_adj 的方式调整的,取值范围为 -1000 到 1000。
该值越大,进程总的badness点数就会越大,进程也就越容易被kill掉。
该值越小,进程总的badness点数就会越小,该进程也就越不容易被kill掉。
oom_score_adj=OOM_SCORE_ADJ_MIN,即-1000,表示该进程不能被kill掉。

(3)一部分是系统打分,主要是根据该task的内存使用情况。主要评分函数:
points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) + mm_pgtables_bytes(p->mm) / PAGE_SIZE;
系统打分就是看物理内存消耗量,主要是三部分,RSS部分,swap file或者swap device上占用的内存情况以及页表占用的内存情况。另外,root进程有3%的内存使用特权,因此这里要减去那些内存使用量
所以最后的公式:
points = 该进程占用的物理内存总数 + 总物理内存 * oom_score_adj值的千分比。

小结:
oom killer 是Linux的系统保护手段,主要是发现系统内存不足时候,为了保护其他系统资源的正常运行时候,系统通过select_bad_process()选择一个最”bad”进程进行kill,这种情况的程序退出,真的很无语,那也体现了端口探测的重要性。

oom killer相关推荐

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

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

  2. linux进程莫名其妙被kill,Linux进程突然被杀掉(OOM killer),查看系统日志

    Linux进程被杀掉(OOM killer),查看系统日志 基本概念: Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是 ...

  3. 理解和配置 Linux 下的 OOM Killer

    原文:http://www.vpsee.com/2013/10/how-to-configure-the-linux-oom-killer/ 最近有位 VPS 客户抱怨 MySQL 无缘无故挂掉,还有 ...

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

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

  5. (转载)Linux Out-of-Memory(OOM) Killer

    Linux有一个特性:OOM Killer,一个保护机制,用于避免在内存不足的时候不至于出现严重问题,把一些无关的进程优先杀掉,即在内存严重不足时,系统为了继续运转,内核会挑选一个进程,将其杀掉,以释 ...

  6. 认真理解 oom killer 备忘

    最近项目测试,发现一个oom killer问题,所以搜集了一些文章,理解并做记录. 现象:做性能测试时,程序自己退出,记录"killed"日志.查了下syslog发现详细记录了问题 ...

  7. jvm系列(十):教你如何成为Java的OOM Killer

    此文出处云时代架构,作者:李艳鹏 教你如何成为Java的OOM Killer 前言 虽然事隔半年,当时排查线上OOM事故的过程记忆犹新,每一个步骤都历历在目,感谢业务组.系统部.压测组.监控与应急部对 ...

  8. ubuntu虚拟机进程被杀死_Linux进程被杀掉(OOM killer),查看系统日志

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

  9. linux进程被杀掉日志,Linux进程突然被杀掉(OOM killer),查看系统日志

    Linux进程被杀掉(OOM killer),查看系统日志 基本概念: Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是 ...

  10. linux内核killler,Linux内核参数overcommit_memory和OOM killer介绍

    什么是Linux Overcommit和OOM overcommit_memory是一个内核对内存分配的一种策略,它有三个可选值:0.1.2. 0. 表示内核将检查是否有足够的可用内存供应用进程使用: ...

最新文章

  1. c语言if判断正确却不进函数,C语言初学者,为什么满足if条件却不进入,求大老解惑...
  2. VUE搭建手机商城心得
  3. php网站发布工具_7款本地搭建PHP环境工具推荐
  4. 让FLASH背景透明-可运用于在网页内的FLASH内嵌入另一个网页
  5. Linux 命令(29)—— ls 命令
  6. js获取ck_js取不到ckeditor textarea值
  7. ElasticSearch近似匹配调研
  8. usb书:圈圈教你玩USB
  9. 交换机在局域网内的日常工作
  10. 英伟达显卡不同架构_【英伟达NVIDIA显卡GPU架构核心代号名称一览】(截止到 2018·08)...
  11. jieba分词的原理
  12. max31865C语言程序,max31865温度传感器通信驱动代码
  13. c语言自学路线图,C语言的知识体系图,C语言学习路线图
  14. vmware虚拟机扩展磁盘空间
  15. 前端最常用的移动App开发方式及技术栈详解
  16. unity android录制视频教程,Unity3d 录屏功能教程指南 | Cross Platform Replay Kit
  17. 【第十一篇】字体设置css变形(transfom)4种
  18. 怎么把python变成中文_又一个奇葩要求,Python是如何将“中文”转“拼音”的?...
  19. idea自动去除导入但未使用的包
  20. PS改变背景图片/颜色(3种方法)

热门文章

  1. 数学模型学习——模糊关系与模糊矩阵
  2. DataFrame函数diff与pct_change区别
  3. 数据分析——matplotlib(3)图片的基本操作
  4. MyBatis和JPA的优劣以及MyBatis-Plus的使用
  5. python中range什么意思?
  6. 高效率同步升压驱动芯片ZCC9428(自主研发)
  7. vc 单文档程序和多文档程序有什么区别?
  8. 计算机游戏活动总结,游戏活动总结
  9. Mac强大Git客户端Tower 基于Linux 内核开发的Git客户端
  10. 【C语言实现游戏】(二)扫雷(递归实现排雷)