Linux系统的OOM Killer处理机制

作者&投稿:狂命 (若有异议请与网页底部的电邮联系)
~ 最近有位 VPS 客户抱怨 MySQL 无缘无故挂掉,还有位客户抱怨 VPS 经常死机,登陆到终端看了一下,都是常见的 Out of memory 问题。这通常是因为某时刻应用程序大量请求内存导致系统内存不足造成的,这通常会触发 Linux 内核里的 Out of Memory (OOM) killer,OOM killer 会杀掉某个进程以腾出内存留给系统用,不致于让系统立刻崩溃。如果检查相关的日志文件(/var/log/messages)就会看到下面类似的 Out of memory: Kill process 信息:
...
Out of memory: Kill process 9682 (mysqld) score 9 or sacrifice child
Killed process 9682, UID 27, (mysqld) total-vm:47388kB, anon-rss:3744kB, file-rss:80kB
httpd invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
httpd cpuset=/ mems_allowed=0
Pid: 8911, comm: httpd Not tainted 2.6.32-279.1.1.el6.i686 #1
...
21556 total pagecache pages
21049 pages in swap cache
Swap cache stats: add 12819103, delete 12798054, find 3188096/4634617
Free swap = 0kB
Total swap = 524280kB
131071 pages RAM
0 pages HighMem
3673 pages reserved
67960 pages shared
124940 pages non-shared
Linux 内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,这部分内存是属于每个进程的,内核直接回收利用的话比较麻烦,所以内核采用一种过度分配内存(over-commit memory)的办法来间接利用这部分 “空闲” 的内存,提高整体内存的使用效率。一般来说这样做没有问题,但当大多数应用程序都消耗完自己的内存的时候麻烦就来了,因为这些应用程序的内存需求加起来超出了物理内存(包括 swap)的容量,内核(OOM killer)必须杀掉一些进程才能腾出空间保障系统正常运行。用银行的例子来讲可能更容易懂一些,部分人取钱的时候银行不怕,银行有足够的存款应付,当全国人民(或者绝大多数)都取钱而且每个人都想把自己钱取完的时候银行的麻烦就来了,银行实际上是没有这么多钱给大家取的。
内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码 linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory() 被触发,然后调用 select_bad_process() 选择一个 “bad” 进程杀掉,如何判断和选择一个 “bad” 进程呢,总不能随机选吧?挑选的过程由 oom_badness() 决定,挑选的算法和想法都很简单很朴实:最 bad 的那个进程就是那个最占用内存的进程。
/**
* oom_badness - heuristic function to determine which candidate task to kill
* @p: task struct of which task we should calculate
* @totalpages: total present RAM allowed for page allocation
*
* The heuristic for determining which task to kill is made to be as simple and
* predictable as possible. The goal is to return the highest value for the
* task consuming the most memory to avoid subsequent oom failures.
*/
unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg,
const nodemask_t *nodemask, unsigned long totalpages)
{
long points;
long adj;
if (oom_unkillable_task(p, memcg, nodemask))
return 0;
p = find_lock_task_mm(p);
if (!p)
return 0;
adj = (long)p-signal-oom_score_adj;
if (adj == OOM_SCORE_ADJ_MIN) {
task_unlock(p);
return 0;
}
/*
* 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) + p-mm-nr_ptes +
get_mm_counter(p-mm, MM_SWAPENTS);
task_unlock(p);
/*
* Root processes get 3% bonus, just like the __vm_enough_memory()
* implementation used by LSMs.
*/
if (has_capability_noaudit(p, CAP_SYS_ADMIN))
adj -= 30;
/* Normalize to oom_score_adj units */
adj *= totalpages / 1000;
points += adj;
/*
* Never return 0 for an eligible task regardless of the root bonus and
* oom_score_adj (oom_score_adj can't be OOM_SCORE_ADJ_MIN here).
*/
return points 0 ? points : 1;
}
上面代码里的注释写的很明白,理解了这个算法我们就理解了为啥 MySQL 躺着也能中枪了,因为它的体积总是最大(一般来说它在系统上占用内存最多),所以如果 Out of Memeory (OOM) 的话总是不幸第一个被 kill 掉。解决这个问题最简单的办法就是增加内存,或者想办法优化 MySQL 使其占用更少的内存,除了优化 MySQL 外还可以优化系统(优化 Debian 5,优化 CentOS 5.x),让系统尽可能使用少的内存以便应用程序(如 MySQL) 能使用更多的内存,还有一个临时的办法就是调整内核参数,让 MySQL 进程不容易被 OOM killer 发现。
我们可以通过一些内核参数来调整 OOM killer 的行为,避免系统在那里不停的杀进程。比如我们可以在触发 OOM 后立刻触发 kernel panic,kernel panic 10秒后自动重启系统。
# sysctl -w vm.panic_on_oom=1
vm.panic_on_oom = 1
# sysctl -w kernel.panic=10
kernel.panic = 10
# echo "vm.panic_on_oom=1" /etc/sysctl.conf
# echo "kernel.panic=10" /etc/sysctl.conf
从上面的 oom_kill.c 代码里可以看到 oom_badness() 给每个进程打分,根据 points 的高低来决定杀哪个进程,这个 points 可以根据 adj 调节,root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠(adj -= 30; 分数越低越不容易被杀掉)。我们可以在用户空间通过操作每个进程的 oom_adj 内核参数来决定哪些进程不这么容易被 OOM killer 选中杀掉。比如,如果不想 MySQL 进程被轻易杀掉的话可以找到 MySQL 运行的进程号后,调整 oom_score_adj 为 -15(注意 points 越小越不容易被杀):
# ps aux | grep mysqld
mysql 2196 1.6 2.1 623800 44876 ? Ssl 09:42 0:00 /usr/sbin/mysqld
# cat /proc/2196/oom_score_adj
0
# echo -15 /proc/2196/oom_score_adj
当然,如果需要的话可以完全关闭 OOM killer(不推荐用在生产环境):
# sysctl -w vm.overcommit_memory=2
# echo "vm.overcommit_memory=2" /etc/sysctl.conf
我们知道了在用户空间可以通过操作每个进程的 oom_adj 内核参数来调整进程的分数,这个分数也可以通过 oom_score 这个内核参数看到,比如查看进程号为981的 omm_score,这个分数被上面提到的 omm_score_adj 参数调整后(-15),就变成了3:
# cat /proc/981/oom_score
18
# echo -15 /proc/981/oom_score_adj
# cat /proc/981/oom_score
3
下面这个 bash 脚本可用来打印当前系统上 oom_score 分数最高(最容易被 OOM Killer 杀掉)的进程:
# vi oomscore.sh
#!/bin/bash
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do
printf "%2d %5d %sn"
"$(cat $proc/oom_score)"
"$(basename $proc)"
"$(cat $proc/cmdline | tr '' ' ' | head -c 50)"
done 2/dev/null | sort -nr | head -n 10
# chmod +x oomscore.sh
# ./oomscore.sh
18 981 /usr/sbin/mysqld
4 31359 -bash
4 31056 -bash
1 31358 sshd: root@pts/6
1 31244 sshd: vpsee [priv]
1 31159 -bash
1 31158 sudo -i
1 31055 sshd: root@pts/3
1 30912 sshd: vpsee [priv]
1 29547 /usr/sbin/sshd -D


设置主uefi os 多硬盘
参考:将Linux系统的home、var目录迁移到新分区 系统信息 :(base) famir@ubuntu:~$ neofetch .-\/+oossssoo+\/-. famir@ubuntu `:+ssssssssssssssssss+:` --- -+ssssssssssssssssssyyssss+- OS: Ubuntu 18.04.2 LTS x86_64 .ossssssssssssssssssdMMMNysssso. Host...

用纯粹的C语言能实现面向对象编程吗?
当然可以!面向对象本身是一种思想,而用哪种语言实现只是一种技术手段。事实上思想和技术的关系本身就是class和object的关系。class oo {\/\/这是面向对象的思想类}; oo java; \/\/java是oo的一个具体的技术实现oo cxx; \/\/c++是oo的一个具体的技术实现拿Windows系统来讲,它是有C语言编写的,但是...

说说常用的UNIX命令?
>> Linux ‖ BSD ‖ Solaris ‖ SCO ‖ HP-UX ‖ AIX ‖ AS400 ‖ Tru64 ‖ IRIX ‖ MacOsXUNIX命令一、UNIX命令格式1、UNIX命令提示符 在命令行下,操作系统会显示一提示符,提示用户在此提示符后可以输入一行命令。不同的Shell有不同的缺省提示符: B Shell和K Shell的缺省提示符为"$"; C Shell的...

公司现在还能免费安装使用Open office吗?
OpenOffice.org 是自由软件,任何人都可以免费下载、使用、及推广它。这是OpenOffice网站的原话,网址为:http:\/\/zh.openoffice.org\/new\/zh_cn\/index.html 你可以放心大胆的使用,不光可以使用OOo,还可以推广。

目前为止,有那些语言可以写操作系统?
根据几年前微软在美国公布的内容,Windows的微内核系统80%是用C++编写,其余部分是C和汇编,底层接口用汇编编写。Linux内核是用C语言写的,中间嵌入了部分汇编代码,底层的部分代码完全是汇编语言(如启动代码),图形环境中有采用perl等语言的,种类较多。DOS早期使用会编写的,后来改C了,当然也经历了B...你要想开发操作...

重装系统问题
Had 7.1,装完以后linux能进去,windows却不能进了,请问是什么回事,该怎么解决呢? 答:这里首先要介绍一下Linux系统设备的命名规则。在Linux里,各种设备和分区的命名方法完全不同于Dos,软驱,硬盘以及硬盘分区都有各自的设备特殊文件,例如: \/dev\/hda 表示第一个IDE硬盘(整个) \/dev\/hda1 表示第一个硬盘的第一个主...

怎么在MacBook上安装kali Linux
macbook安装kali linux(Debian)当你尝试在macbook上single boot一个debian或kali linux时(如果是ubuntu或BT的话,你会发现过程会异常的顺利),你会发现默认安装的GRUB或LILO都无法引导你的操作系统。这个问题也让我困惑了很长时间(因为默认安装的grub是0.9 这个版本不是efi bootable的)。经过长时间的...

java开发需要学习什么?
Java OO程序设计基础,包括 J2sdk基础、Java面向对象基础、Java API使用、数据结构及算法基础、Java AWT图形界面程序开发;J2SE平台Java程序设计,包括Swing图形程序设计, Socket网络应用程序设计,对象序列化,Java 常用数据结构,Applet,流和文件,多线程程序设计;Java桌面系统项目开发,4~5人组成一个项目组,项目大小为(15人...

Linux系统关机的时候出现错误,提示:shutdown:hda System halted.这是...
你好,你这个不是报错,这句话的意思是你的系统已经成功关闭,halted的意思就是已经关闭,只是因为电源管理的问题,导致系统无法将你的电脑断电。 这个可以解决也...hostchsoo 采纳率:67% 擅长: Linux JAVA相关 Windows 剑侠情缘 其他回答 修改grub.conf文件,在使用中的grub后面加入以下行:kernel \/boot\/vmlinuz-2.6.21...

xquartz是什么?干嘛的?怎么用?
在系统的安装盘中有x11的安装包,双击就可以安装。安装后对你的系统没有什么影响,就是在系统预置中多了个x11的选项。还有就是在启动x11应用程序时,x11环境会自动启动。如果不想安装x11,可以试试nenooffice(好像是这样写的)。它就是基于oo编写的,并且不用x11支持。简单点说一般用户没有用处,除非...

桑植县18979376906: linux oom 内存超过多少会被kill -
籍饶郁金: OOM_killer是Linux自我保护的方式,当内存不足时不至于出现太严重问题,有点壮士断腕的意味 在kernel 2.6,内存不足将唤醒oom_killer,挑出/proc//oom_score最大者并将之kill掉 为了保护重要进程不被oom-killer掉,我们可以:echo -17 > /...

桑植县18979376906: Linux操作系统入门到精通? -
籍饶郁金: Linux中常用命令是必须掌握的,它们与系统状态、目录、文件、网络等相关.本节讲解常用的Linux命令,为今后学习更复杂的命令打下良好基础.系统工作命令1. 查看系统信息uname -a 显示当前系统相关信息uname -r 显示系统内核版本...

桑植县18979376906: 在linux操作系统上oracle数据库的启动和停止 -
籍饶郁金: 首先su 到 oracle 用户$ sqlplus "/ as sysdba" sql> startup 即可启动数据库 exit 退出$ lsnrctl start (启动监听)$ sqlplus "/ as sysdba" sql> shutdown 即可停止数据库 exit 退出$ lsnrctl stop (停止监听)

桑植县18979376906: Linux系统中密码破解大全
籍饶郁金: (一)Linux 系统密码破解 1.在grub选项菜单按E进入编辑模式 2.编辑kernel那行 /init 1 (或/single) 3.按B重启 4.进入后执行下列命令 root@#passwd root (设置root的密码) Enter new unix password:输入新的密码 root@#init 6 (二)debian ...

桑植县18979376906: Linux系统由哪些部分组成? -
籍饶郁金: Linux系统本身是个软件的概念(当然,其无法脱离硬件系统而存在). 其三个基本组成部分:【启动引导程序】 即bootloader,常见的如Grub.用于引导系统启动,加载内核到系统内存并启动内核.【内核】 即操作系统核心.包含硬件驱动模块,为上层应用提供统一易用的硬件操作接口;负责系统任务调度与分配,保证系统资源被合理有效地利用.内核通过shell接收用户指令并执行.【文件系统】 如现在的日志文件系统ext2/ext3.Linux的应用程序按照一定的分类,以文件系统的形式组织存放在磁盘或分区上.内核启动后挂载文件系统(第一个挂载的是根文件系统).

桑植县18979376906: 如何查看linux操作系统版本 -
籍饶郁金: 查看系统发型版本1 方法1 对于linux系统而已,有成百上千个发行版.对于发行版的版本号查看方法 如以centos为例.输入lsb_release -a即可 该命令适用于所有的linux,包括Redhat、SuSE、Debian等发行版2 方法2 如果如上图,没有这个命令 ...

桑植县18979376906: LINUX操作系统的启动过程 -
籍饶郁金: 一、启动内核 首先介绍启动内核部分.电脑启动时,BIOS装载MBR,然后从当前活动分区启动,LILO获得引 导过程的控制权后,会显示LILO提示符.此时如果用户不进行任何操作,LILO将在等待制定 时间后自动引导默认的操作系统,而如...

桑植县18979376906: ARM - Linux嵌入式系统的基本组成,各部分的作用 -
籍饶郁金: ARM-Linux嵌入式系统的基本组成:1、bootloader:相当于PC机的 BIOS,用于引导基本操作系统.2、基本 Linux 系统,作用就不用多说了,就是应用软件的基础平台.3、文件系统,作用就是用来管理嵌入式系统的存储空间.本来应该算操作...

桑植县18979376906: Linux系统一共有几种,它们的区别是什么 -
籍饶郁金: Linux的本质来说,它只是操作系统的核心,负责控制硬件、管理文件系统、程序进程等.Linux Kernel(内核)并不负责提供用户强大的应用程序,没有编译器、系统管理工具、网络工具、Office套件、多媒体、绘图软件等,这样的系统也就无...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网