从Out of memory来看是内存超出了,后面的 Kill process[PID] [process name] score好像和进程有关了,下面我们就一起来看看linux 终端报错 Out of memory: Kill process[PID] [process name] score问题分析
看到屏幕上都是 Out of memory: Kill process[PID] [process name] score,虽然知道这是linux自我保护进行内存清理动作,但是为了知道更多的细节进行了学习。
【原因分析】
Out of memory 问题,这通常是因为某时刻应用程序大量请求内存导致系统内存不足造成的,这通常会触发 Linux 内核里的 Out of Memory (OOM) killer,OOM killer 会杀掉某个进程以腾出内存留给系统用,不致于让系统立刻崩溃。
Linux 内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,这部分内存是属于每个进程的,内核直接回收利用的话比较麻烦,所以内核采用一种过度分配内存(over-commit memory)的办法来间接利用这部分 “空闲” 的内存,提高整体内存的使用效率。一般来说这样做没有问题,但当大多数应用程序都消耗完自己的内存的时候麻烦就来了,因为这些应用程序的内存需求加起来超出了物理内存(包括 swap)的容量,内核(OOM killer)必须杀掉一些进程才能腾出空间保障系统正常运行。
可能有些同学发现内存还剩下很多啊?怎么还是在报错内存不够呢?那是因为32位的系统,如果Low-memory耗尽,就会导致这个问题的出现。那low-memory又是怎么回事呢?
内核使用low memory来跟踪所有的内存分配,这样的话一个16GB内存的系统比一个4GB内存的系统,需要消耗更多的low memory,可能有4倍之多。这种额外的压力从你刚启动系统那一刻就开始存在了,因为内核结构必须为潜在的跟踪四倍多的内存分配而调整大小
OOM Killer 就是一层保护机制,用于避免 Linux 在内存不足的时候不至于出太严重的问题,把无关紧要的进程杀掉,有些壮士断腕的意思。
在 32 位CPU 架构下寻址是有限制的。Linux 内核定义了三个区域:
# DMA: 0x00000000 - 0x00999999 (0 - 16 MB)
# LowMem: 0x01000000 - 0x037999999 (16 - 896 MB) - size: 880MB
# HighMem: 0x038000000 - <硬件特定>
LowMem 区 (也叫 NORMAL ZONE ) 一共 880 MB,而且不能改变(除非用 hugemem 内核)。对于高负载的系统,就可能因为 LowMem 利用不好而引发 OOM Killer 。一个可能原因是 LowFree 太少了,另外一个原因是 LowMem 里都是碎片,请求不到连续的内存区域。
另外,在64位系统下low-memory是所有的内存空间。
查看low memory 和 high memory 的状态:
[root@localhost ~]# free -lm
total used free shared buffers cached
Mem: 32105 11305 20800 0 176 5402
Low: 32105 11305 20800
High: 0 0 0
-/+ buffers/cache: 5726 26379
Swap: 32767 0 32767
【OOM killer原理】
从oom_killer给每个进程打分,根据 points 的高低来决定杀哪个进程,这个points可以调节,root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠( -= 30; 分数越低越不容易被杀掉)。我们可以在用户空间通过操作每个进程的内核参数来决定哪些进程不这么容易被 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
【解决方法】
知道了原理,那么怎么解决呢?
一、增大内存。
内存不够咱们肯定要增加啊?不然怎么叫服务器呢?
二、升级到64位操作系统。
64位的操作系统没有对low-memory限制。
三、使用hugemem内核。
这种内核以不同的方式分割low/high memory,而且在大多数情况下会提供足够多的low memory到high memory的映射。在大多数案例中,这是一个很简单的修复方法:安装hugemem kernel RPM包,然后重启即可。
四、配置 OOM killer
通过一些内核参数来调整 OOM killer 的行为,避免系统在那里不停的杀进程。比如我们可以在触发 OOM 后立刻触发 kernel panic,kernel panic 10秒后自动重启系统。
echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=10" >> /etc/sysctl.conf
sysctl -p
五、关闭/打开oom-killer(慎用)
echo "0" > /proc/sys/vm/oom-kill
echo "1" > /proc/sys/vm/oom-kill