1. 概念描述
Linux内核内存管理使用OOM killer(Out-Of-Memory killer)机制,在系统内存不足时,选择性杀死一些进程以释放内存,以使系统继续运行。
2. OOM killer产生的原因
2.1 malloc 内存分配
By default, Linux follows an optimistic memory allocation strategy.
This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. This is a really bad bug. In case it turns out that the system is out of memory, one or more processes will be killed by the infamous OOM killer.
如上为malloc的manpage节选,说明malloc返回非空指针并不代表指向内存就是可用的,而当系统没有内存时,会通过杀死进程来腾出内存。
2.2 Memory Overcommit
此机制是指操作系统承诺给进程的内存大小超过实际可用物理内存。按照常规理解,内存分配有多少就分配多少,再申请就返回失败。但实际上这种策略是有些浪费内存,因为进程实际使用到的内存往往比申请的内存少。
按照Linux的算法,物理内存页的分配发生在使用瞬间,而不是在申请瞬间。overcommit针对 的也是内存申请,而不是内存分配。
Linux是允许memory overcommit的,即当申请的内存超过分配物理内存一定程度内,仍然可以申请成功。当实际使用时超过可分配物理内存时,利用OOM机制挑选一个进程出来杀死,以释放部分内存,如若不够则继续杀死进程,也可以配置内核参数panic_on_oom进行自动重启系统。
3. 虚拟内存分配
3.1 影响参数
3.1.1 overcommit_memory
用以控制内核的overcommit策略开关。
可选值 | 含义 |
---|---|
OVERCOMMIT_GUESS(0) | 视情况允许overcommit。系统在为应用进程分配虚拟地址空间时,会判断当前申请的虚拟地址空间大小是否超过剩余内存大小,如果超过,则虚拟地址空间分配失败。 |
OVERCOMMIT_ALWAYS(1) | 总是允许overcommit。系统在为应用进程分配虚拟地址空间时,完全不进行限制,避免了fork可能产生的失败,但由于malloc是先分配虚拟地址空间,而后通过异常陷入内核分配真正的物理内存,在内存不足的情况下,完全屏蔽了应用进程对系统内存状态的感知,即malloc总是能成功,但内存不足时会引起系统OOM杀进程。 |
OVERCOMMIT_NEVER(2) | 禁止overcommit,根据系统内存状态确定虚拟地址空间上限。然而很多情况下,进程的虚拟地址空间占用远大于其实际占用的物理内存,这样一旦内存使用量上去以后,对于一些动态产生的进程(需要复制父进程地址空间)则很容易创建失败,如果业务过程没有过多的这种动态申请内存或者创建子进程,则影响不大,否则会产生比较大的影响 |