Linux OOM Killer机制 以及防止被OOM Killer杀死的方法_linux 设置 redis 内存 防止oom(2)

最全的Linux教程,Linux从入门到精通

======================

  1. linux从入门到精通(第2版)

  2. Linux系统移植

  3. Linux驱动开发入门与实战

  4. LINUX 系统移植 第2版

  5. Linux开源网络全栈详解 从DPDK到OpenFlow

华为18级工程师呕心沥血撰写3000页Linux学习笔记教程

第一份《Linux从入门到精通》466页

====================

内容简介

====

本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。

华为18级工程师呕心沥血撰写3000页Linux学习笔记教程

本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。

需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

if (!is_memcg_oom(oc)) {
	blocking_notifier_call_chain(&oom_notify_list, 0, &freed);
	if (freed > 0)
		/* Got some memory back in the last second. */
		return true;
}

/*
 * If current has a pending SIGKILL or is exiting, then automatically
 * select it.  The goal is to allow it to allocate so that it may
 * quickly exit and free its memory.
 */
if (task_will_free_mem(current)) {
	mark_oom_victim(current);
	wake_oom_reaper(current);
	return true;
}

/*
 * The OOM killer does not compensate for IO-less reclaim.
 * pagefault_out_of_memory lost its gfp context so we have to
 * make sure exclude 0 mask - all other users should have at least
 * ___GFP_DIRECT_RECLAIM to get here. But mem_cgroup_oom() has to
 * invoke the OOM killer even if it is a GFP_NOFS allocation.
 */
if (oc->gfp_mask && !(oc->gfp_mask & __GFP_FS) && !is_memcg_oom(oc))
	return true;

/*
 * Check if there were limitations on the allocation (only relevant for
 * NUMA and memcg) that may require different handling.
 */
oc->constraint = constrained_alloc(oc);
if (oc->constraint != CONSTRAINT_MEMORY_POLICY)
	oc->nodemask = NULL;
check_panic_on_oom(oc);

if (!is_memcg_oom(oc) && sysctl_oom_kill_allocating_task &&
    current->mm && !oom_unkillable_task(current) &&
    oom_cpuset_eligible(current, oc) &&
    current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) {
	get_task_struct(current);
	oc->chosen = current;
	oom_kill_process(oc, "Out of memory (oom_kill_allocating_task)");
	return true;
}

select_bad_process(oc);
/* Found nothing?!?! */
if (!oc->chosen) {
	dump_header(oc, NULL);
	pr_warn("Out of memory and no killable processes...\n");
	/*
	 * If we got here due to an actual allocation at the
	 * system level, we cannot survive this and will enter
	 * an endless loop in the allocator. Bail out now.
	 */
	if (!is_sysrq_oom(oc) && !is_memcg_oom(oc))
		panic("System is deadlocked on memory\n");
}
if (oc->chosen && oc->chosen != (void *)-1UL)
	oom_kill_process(oc, !is_memcg_oom(oc) ? "Out of memory" :
			 "Memory cgroup out of memory");
return !!oc->chosen;

}


然后调用check\_panic\_on\_oom(oc),这个函数决定采用哪种方式处理OOM。而决定哪种方式依赖于内核参数panic\_on\_oom。panic\_on\_oom的枚举值有:


默认值 0。启动OOM Killer


1 在有cpuset、memory policy、memcg的约束情况下的OOM,可以考虑不panic,而是启动OOM killer 


2。无论那种情况,强制进入kernel panic(直接死机)。



/*

  • Determines whether the kernel must panic because of the panic_on_oom sysctl.
    */
    static void check_panic_on_oom(struct oom_control oc)
    {
    //0表示启动OOM killer,因此直接return了
    if (likely(!sysctl_panic_on_oom))
    return;
    //2是强制panic,不是2的话,还可以商量
    if (sysctl_panic_on_oom != 2) {
    /

    * panic_on_oom == 1 only affects CONSTRAINT_NONE, the kernel
    * does not panic for cpuset, mempolicy, or memcg allocation
    * failures.
    /
    /

    *在有cpuset、memory policy、memcg的约束情况下的OOM,可以考虑不panic,而是启动OOM killer
    /
    if (oc->constraint != CONSTRAINT_NONE)
    return;
    }
    /
    Do not panic for oom kills triggered by sysrq */
    if (is_sysrq_oom(oc))
    return;
    dump_header(oc, NULL);
    //死机
    panic(“Out of memory: %s panic_on_oom is enabled\n”,
    sysctl_panic_on_oom == 2 ? “compulsory” : “system-wide”);
    }

如果决定发起OOM killer,判断系统参数oom\_kill\_allocating\_task,来决定选择哪些进程去kill。oom\_kill\_allocating\_task的值:


1 选择kill引起oom的进


其他值 调用select\_bad\_process(oc),选择最bad的进程。


如果没有配置该值,则调用select\_bad\_process(oc),接着调用oom\_evaluate\_task(p, oc),接着调用oom\_badness(task, oc->totalpages)来对进程打分,


 


   从oom\_kill.c 代码里可以看到 oom\_badness() 给每个进程打分,根据 points 的高低来决定杀哪个进程,这个 points 可以根据 adj 调节,root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠(分数越低越不容易被杀掉)。


我们可以在用户空间通过操作每个进程的 oom\_adj 内核参数来决定哪些进程不这么容易被 OOM killer 选中杀掉。比如,如果不想 MySQL 进程被轻易杀掉的话可以找到 MySQL 运行的进程号后,调整 /proc/PID/oom\_score\_adj 为 -15(注意 points越小越不容易被杀)防止重要的系统进程触发(OOM)机制而被杀死,内核会通过特定的算法给每个进程计算一个分数来决定杀哪个进程,每个进程的oom分数可以在/proc/**PID**/oom\_score中找到。每个进程都有一个oom\_score的属性,oom killer会杀死oom\_score较大的进程,当oom\_score为0时禁止内核杀死该进程。


设置/proc/PID/oom\_adj可以改变oom\_score,oom\_adj的范围为【-17,15】,其中15最大-16最小,-17为禁止使用OOM,至于为什么用-17而不用其他数值(默认值为0),这个是由linux内核定义的,查看内核源码可知:路径为linux-xxxxx/include /uapi/linux/oom.h。


![](https://img-blog.csdn.net/20150506143916611?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGl1a3Vhbjcz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)


      保证某个进程不被内核杀掉可以这样操作:  
             



echo -17 > /proc/$PID/oom_adj


  
        例如防止sshd被杀,可以这样操作:  
            



pgrep -f “/usr/sbin/sshd” | while read PID;do echo -17 > /proc/$PID/oom_adj;done


#### 查看所有进程的oom\_score排行前十的进程



#!/bin/bash
for proc in ( f i n d / p r o c − m a x d e p t h 1 − r e g e x ′ / p r o c / [ 0 − 9 ] + ′ ) ; d o p r i n t f " " (find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do printf "%2d %5d %s\n" \ " (find/procmaxdepth1regex/proc/[09]+);doprintf""(cat p r o c / o o m s c o r e ) "   " proc/oom_score)" \ " proc/oomscore)" "(basename p r o c ) "   " proc)" \ " proc)" "(cat $proc/cmdline | tr ‘\0’ ’ ’ | head -c 50)"
done 2>/dev/null | sort -nr | head -n 10


#### 防止OOM Killer的方法


综上所述,知道了OOM killer的原理以及约束后,可以总结出以下几种方法来避免进程被OOM killer杀死。


**1.修改Overcommit策略为1或2。(不推荐)**


**2.修改panic\_on\_oom参数为2,直接死机(不推荐)。**


**3.修改进程oom\_adj和oom\_score\_adj来降低oom\_score的得分,降低被OOM killer选中的几率。**


**oom\_adj可选值:[-17,15] -17表示禁止OOM killer**


**修改方式**



echo -17 > /proc/$PID/oom_adj


**oom\_score\_adj可选值[**-1000,1000**]。**0表示用户不调整oom\_score,负值表示要在实际打分值上减去一个折扣,正值表示要惩罚该task,也就是增加该进程的oom\_score。


例如如果oom\_score\_adj设定-500,那么表示实际分数要打五折(基数是totalpages),也就是说该任务实际使用的内存要减去可分配的内存上限值的一半。


修改方式:




![](https://img-blog.csdnimg.cn/img_convert/9a8cb5f8c0ec69e6499adead0da6e95b.png)


最全的Linux教程,Linux从入门到精通

======================

1.  **linux从入门到精通(第2版)**

2.  **Linux系统移植**

3.  **Linux驱动开发入门与实战**

4.  **LINUX 系统移植 第2版**

5.  **Linux开源网络全栈详解 从DPDK到OpenFlow**



![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/59742364bb1338737fe2d315a9e2ec54.png)



第一份《Linux从入门到精通》466页

====================

内容简介

====

本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。



![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/9d4aefb6a92edea27b825e59aa1f2c54.png)



**本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。**

> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值