OOM killer机制
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OOM killer机制相关的知识,希望对你有一定的参考价值。
今天早晨发现我的tomcat进程无缘无故被杀死了,查看了tomcat内存监控,发现jvm内存并没有什么异常,并不是java内存溢出造成的,进到服务器控制台发现
然后查了一下
这个问题的原因是由于系统内存不足导致触发OOM保护机制。OOM Killer(Out of memory killer) 就是一层保护机制,用于避免 Linux 在内存不足的时候不至于出太严重的问题,将占用内存大的进程杀死,以保证系统正常运行。
还有一种情况,内存够用,但还是触发了 OOM 杀死进程。这里涉及到一个 Low Memory 的知识点。内核使用 Low Memory 来跟踪所有的内存分配。
解释一下low memory,与之对应的有一个high memory
不过high memory只存在于32位的linux。64位系统下不会有high memory,因为64位虚拟地址空间非常大(分给kernel的也很大),完全能够直接映射全部物理内存。可以看到我的系统位数是64位的
32位的CPU,最大寻址范围为2^32 - 1也就是4G的线性地址空间。Linux简化了分段机制,使得虚拟地址与线性地址总是一致的。linux一般把这个4G的地址空间划分为两个部分:其中0~3G为用户程序地址空间,虚地址0x00000000到0xBFFFFFFF,供各个进程使用;3G~4G为内核的地址空间,虚拟地址0xC0000000到0xFFFFFFFF, 供内核使用。(注意,ARM架构不是3G/1G划分的,而是2G/2G划分。这里以3G/1G划分作讲解)。如下图所示:
可以看出,每个进程都有自己的私有用户空间(0-3GB),这个空间对系统中的其他进程是不可见的。最高的1GB内核空间则由则由所有进程以及内核共享。可见,内核最多寻址1G的虚拟地址空间。
Linux 内核采用了最简单的映射方式来映射物理内存,即把物理地址+PAGE_OFFSET按照线性关系直接映射到内核空间。PAGE_OFFSET大小为0xC000000.但是linux内核并没有把整个1G空间用于线性映射,而只映射了最多896M物理内存,预留了最高端的128M虚拟地址空间给IO设备和其他用途。
所以,当系统物理内存较大时,超过896M的内存区域,内核就无法直接通过线性映射直接访问了。这部分内存被称作high memory。相应的可以映射的低端物理内存称为Low memory.
结论:
1)high memory针对的是物理内存,不是虚拟内存。
2)high memory也是被内核管理的(有对应的page结构),只是没有映射到内核虚拟地址空间。当内核需要分配high memory时,通过kmap等从预留的地址空间中动态分配一个地址,然后映射到high memory,从而访问这个物理页。high memory映射到内核地址空间一般是暂时性的映射,不是永久映射。
3)high memory和low memory一样,都是参与内核的物理内存分配,都可以被映射到内核地址空间,也都可以被映射到用户地址空间。
4)物理内存<896M时,没有high memory,因为所有的内存都被kernel直接映射了。
5)64位系统下不会有high memory,因为64位虚拟地址空间非常大(分给kernel的也很大),完全能够直接映射全部物理内存。
OOM Killer(Out of memory killer)
Linux 内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀掉。
内存不足将唤醒oom_killer,挑出/proc/<pid>/oom_score最大者并将之kill掉
防止重要的系统进程触发(OOM)机制而被杀死:可以设置参数/proc/<PID>/oom_adj为-17,可临时关闭linux内核的OOM机制。
以上是关于OOM killer机制的主要内容,如果未能解决你的问题,请参考以下文章
Linux OOM-killer机制(out of memory)