Linux 内存耗尽时,内核凭什么杀你的进程?
跑着跑着系统突然把你的进程干掉了,日志里只剩一句
核心机制藏在
评分不只是看 RSS。内核还会把子进程的内存累计到父进程头上,加上 swap 占用、页表大小这些容易被忽略的项。所以一个 fork 了好多 worker 的 master 进程,即使自己不怎么吃内存,总分也可能很高——这是很多人被杀之后一脸懵的原因。
整个流程是这样的:内核在分配物理页时发现已经没有可回收的页了(free + reclaimable 都低于 watermark),就唤醒 OOM killer。它遍历所有进程算分,排除掉内核线程、oom_score_adj=-1000 的免疫进程、正在退出状态的进程,然后从最高分开始往下杀。杀一个之后会等一小段时间看内存压力是否缓解,不够就继续杀下一个。
下次看到进程被杀,别急着怪运气差。去查
#CS
跑着跑着系统突然把你的进程干掉了,日志里只剩一句
Out of memory: Killed process 1234。很多人以为 OOM killer 是随机开刀,其实内核有一套相当精密的评分系统。核心机制藏在
/proc/<pid>/oom_score 里。内核会给每个进程算一个 0–1000 的分数,分数越高越先死。计算基础是进程占用的内存比例——你吃掉的物理内存越多,得分自然越高。但真正有意思的是 oom_score_adj,这个值范围 -1000 到 +1000,会叠加到原始分数上做偏移。sshd 这类关键守护进程默认把自己设成 -1000,相当于免疫;而那些 oom_score_adj=0 的普通进程就得裸奔,全靠实际内存占用量拼排名。评分不只是看 RSS。内核还会把子进程的内存累计到父进程头上,加上 swap 占用、页表大小这些容易被忽略的项。所以一个 fork 了好多 worker 的 master 进程,即使自己不怎么吃内存,总分也可能很高——这是很多人被杀之后一脸懵的原因。
整个流程是这样的:内核在分配物理页时发现已经没有可回收的页了(free + reclaimable 都低于 watermark),就唤醒 OOM killer。它遍历所有进程算分,排除掉内核线程、oom_score_adj=-1000 的免疫进程、正在退出状态的进程,然后从最高分开始往下杀。杀一个之后会等一小段时间看内存压力是否缓解,不够就继续杀下一个。
下次看到进程被杀,别急着怪运气差。去查
dmesg 里的 OOM 日志,看看那个进程的 oom_score 到底是多少——大概率它真的是吃内存最多的那个。#CS