1、介绍
OOM killer(Out Of Memory killer)是Linux内核的一个机制,该机制会在内存分配失败的时候被触发,然后根据配置来决定是下一步策略:或者引起系统panic而重启,或者将一些bad的进程kill掉。
2、OOM相关参数
OOM的参数可以通过应用层来进行设置,这些接口一般都在/proc/sys/vm下。
参数 | 说明 | 可选值 | 可选值说明 |
panic_on_oom | 用来控制当内存不足时是否启用OOM | 0 | 内存不足时,启动 OOM killer。 |
1 | 内存不足时,有可能会触发 kernel panic(系统重启),也有可能启动 OOM killer。 | ||
2 | 内存不足时,表示强制触发 kernel panic,内核崩溃GG(系统重启)。 | ||
oom_kill_allocating_task | 用来决定杀掉哪种进程 | 0 | 会 kill 掉得分最高的进程。 |
非0 | 会kill 掉当前申请内存而触发OOM的进程。 PS. 一些系统进程(如init)或者被用户设置了oom_score_adj的进程可能会kill不掉。 |
||
oom_dump_tasks | 记录日志,可以记录进程标识信息、该进程使用的虚拟内存总量、物理内存、进程的页表信息等。 | 0 | 关闭打印上述日志。在大型系统中,可能存在上千进程,逐一打印使用内存信息可能会造成性能问题。 |
1 | 由 OOM 导致 kernel panic 时,打印进程内存使用情况。 | ||
2 | 没有找到符合条件的进程 kill 时,打印进程内存使用情况。 | ||
3 | 找到符合条件的进程并 kill 时,打印进程内存使用情况。 | ||
overcommit_memory | 用来控制进程对内存过量使用的应对策略 | 0 | 允许进程轻微过量使用内存,但对于大量过载请求则不允许(默认) |
1 | 永远允许进程overcommit | ||
2 | 永远禁止overcommit。系统内存可使用量减少,但可调节。如果内存不能超用了,也就不会触发OOM。 | ||
3、kill机制
每个进程都有如下几个参数:
/proc/xxx/oom_score
/proc/xxx/oom_score_adj
/proc/xxx/oom_adj
如果我们设置了panic_on_oom为0或者1的时候,一旦OOM被触发,就会寻找oom_score分数高的进程,将其kill掉。
oom_score的值由两部分组成:
1)系统根据该进程的内存占用情况打分,进程的内存开销是变化的,所以该值也会动态变化。
2)用户可以设置的 oom_score_adj
,范围是 -1000
到 1000
2.1)
如果用户将该进程的 oom_score_adj 设定成 -1000,表示禁止OOM killer 杀死该进程。
2.2)如果设置为负数,表示分数会打一定的折扣。
2.3)如果设置为正数,分数会增加,可以优先杀死该进程。
2.4)如果设置为0 ,表示用户不调整分数,0 是默认值。
我们可以试试,修改我们写的程序的oom_score_adj,看它的oom_score是否有变化:
$ cat /proc/11058/oom_score_adj
0
$ cat /proc/11058/oom_score
0
$ echo 20 > /proc/11058/oom_score_adj
$ cat /proc/11058/oom_score
20
$ echo 30 > /proc/11058/oom_score_adj
$ cat /proc/11058/oom_score
30
$ echo -20 > /proc/11058/oom_score_adj
bash: echo: write error: Permission denied
$ echo "-100" > /proc/11058/oom_score_adj
bash: echo: write error: Permission denied
至于为什么负数不能,我也不清楚,需要后续探讨。
我们可以用如下命令查看系统oom_score最高的进程:
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do printf "%2d %5d %s\n" "$(cat $proc/oom_score)" "$(basename $proc)" "$(cat $proc/cmdline | tr '\0' ' ' | head -c 50)"; done 2>/dev/null | sort -nr | head -n 10
59 1847 compiz
30 11058 ./mymain
25 1157 /usr/lib/xorg/Xorg -core :0 -seat seat0 -auth /var
12 2022 /usr/lib/x86_64-linux-gnu/fwupd/fwupd
12 1883 /usr/lib/evolution/evolution-calendar-factory
11 1892 /usr/bin/gnome-software --gapplication-service
10 2041 /usr/lib/evolution/evolution-calendar-factory-subp
10 1959 /usr/lib/evolution/evolution-calendar-factory-subp
10 1906 nautilus -n
9 2232 /usr/lib/gnome-terminal/gnome-terminal-server