关于32位Linux系统内存溢出问题的情况及几种常见解决方法

由于近期Xenserver系统的OOMkill引起的批量虚拟机hang死以及刀片宕机重启问题,所以针对Out of memory 问题进行了了解和熟悉。

根据查阅网上一些文档LINUX系统具有OOMKiller的保护机制,用于避免 Linux 在内存不足的时候不至于出太严重的问题,把一些无关紧要的进程杀掉,以保证系统的正常运行。

 

内存是通过指针寻址的,因而CPU的字长决定了CPU所能管理的地址空间的大小,该地址空间就被称为虚拟地址空间,因此32位CPU的虚拟地址空间大小是2的32次方=4 294 967 296为4G,这和实际的物理内存数量无关。
Linux内核将虚拟地址空间分成了两部分:

一部分是用户进程可用的,这部分地址是地址空间的低地址部分,从0到TASK_SIZE,称为用户空间;

一部分是由内核保留使用的,这部分地址是地址空间的高地址部分,从KERNELBASE到结束,称为内核空间;

所以在32位系统,一个进程的可寻址范围是有限的

Linux内核定义了下面三个区域:

# DMA: 0x00000000 -  0x00999999 (0 - 16 MB)

# LowMem: 0x01000000 - 0x037999999 (16 -896 MB) - size: 880MB

# HighMem: 0x038000000 - <硬件特定>

其中LowMem 区 (也叫 NORMALZONE ) 一共 880 MB,而且不能改变(除非用 hugemem 内核)。对于高负载的系统,就可能因为 LowMem 利用不好而引发 OOM Killer 。一个可能原因是 LowFree 太少了,另外一个原因是 LowMem 里都是碎片,请求不到连续的内存区域

检查当前 LowFree 的值:

# cat /proc/meminfo |grep LowFree

检查LowMem内存碎片:

# cat /proc/buddyinfo

上面这条命令要在 2.6 Kernel 环境下有效。

 

有如下方法可以解决该问题:

1.升级到64位系统,这是最好的方法,因为此时内核的寻址范围为2的64次方,所有内存都属low memory,如此时提示out of memory,则真的是low memory耗尽了。(目前云桌面xenserverlinux32SMP内核2.6.32.12-0.7.1版本)

2. 如必须使用32位系统,那么可以使用hugemem内核,此时内核会以不同的方式分割low/high memory,而大多数情况下会提供足够多的low memory至high memory的映射,此时很简单的一个修复方法是可以安装hugemem内核包,然后重启。

 

备注:RedHat建议当物理内存在16GB之内,SMP” kernel,16GB-64GB之间使用”Hugemem” kernel.这是因为虚拟地址空间里有1G用于内核空间,而3G用于用户空间。而关健的一些数据结构是存放在1G内核空间的,在管理32G内存当中,需要用到0.5G来用于管理这些物理内存(容易触发OOM killer).虽然32OS,内核和用户空间的比例都是13,但Hugemem打了一个补丁,使比例成为4G:4G,即使内核空间和用户空间相互独立,所以也会有性能上的损失,因为应用程序的运行,通常会有内核和用户空间的切换。所以如果内存大于16G,建议使用64位的OS

 

 3.如果hugemem内核也用不了,那么我们可以尝试将/proc/sys/vm/lower_zone_protection的值设为250或更大,可使用如下命令查看和设置该值:

       cat /proc/sys/vm/lower_zone_protection

       echo250 > /proc/sys/vm/lower_zone_protection

       或者可以修改/etc/sysctl.conf文件,以便重启后生效,添加的内容如下:

       vm.lower_zone_protection= 250

 

注:RHEL 4 ,新增了一个参数: vm.lower_zone_protection 。这个参数默认的单位为 MB,默认 0 的时候,LowMem 16MB。建议设置vm.lower_zone_protection = 200 甚至更大以避免 LowMem 区域的碎片,能解决这个问题 (这参数就是解决这个问题出来的)

    4.实在没办法,那么我们把oom-killer关掉,不过该选项可能导致系统挂起,故要看实际情况使用。

       查看当前的oom-killer的状态:cat /proc/sys/vm/oom-kill

       关闭/打开oom-killer:

       echo"0" > /proc/sys/vm/oom-kill

       echo"1" > /proc/sys/vm/oom-kill

       或者直接加到/etc/sysctl.conf文件,内容如下:

       vm.oom-kill= 0

       此时,当进程被oom-killer尝试杀死而没有成功时,会把相关信息记录到/var/log/messages文件中,信息如下:

       "Wouldhave oom-killed but /proc/sys/vm/oom-kill is disabled"

 

    5.或者不把oom-killer关掉,只针对单一进程处理,把某个进程保护起来,此时,我们可以使用如下命令:

       echo-17 > /proc/[pid]/oom_adj

       /proc/[pid]/oom_adj中oom_adj的取值范围是-17~15,当该值为-17时,系统将不会杀死指定pid的进程,而-16~15则会使得进程的/proc/[pid]/oom_adj值呈指数(K*2^n)形式递增,即它们被杀掉的可能性呈指数递增。针对init(进程号为1)这个进程,无论该值设为多少都不会被杀。

 

6.另外打ctx xenserver024和0332个补丁也或可避免该OOMkill问题的出现。

你可能感兴趣的:(Linux系统)