帮你快速理解、总结文档立即下载

OOM Killer 分析与处理

最近更新时间:2026-08-24 18:27:31
我的收藏

OOM Killer 概述

当系统物理内存耗尽且无法回收足够内存时,Linux 内核会调用 OOM Killer(Out-Of-Memory Killer)机制,选择一个进程将其终止以释放内存,避免系统崩溃。
OOM Killer 的触发流程:

关键概念
调用 OOM Killer 的进程 ≠ 被杀的进程。调用者只是"恰好触发内存分配失败的那个进程",被杀的是 oom_score 最高的进程。
OOM Killer 是内核的兜底保护机制,触发说明系统内存已经严重不足。

如何确认发生了 OOM

查看内核环形缓冲区(ring buffer)中的日志消息,是排查 OOM 事件的首选方法。

方法一:使用 dmesg 查看内核日志

dmesg -T | grep -i "oom-killer\\|out of memory\\|Killed process"

方法二:使用 journalctl 查看内核日志

说明:journalctl 是 systemd 提供的日志查询工具,可按时间范围筛选内核日志,适用于配置了 systemd 的系统:
journalctl -k --since "1 hour ago" | grep -i "oom\\|killed process"

方法三:查看系统日志文件

对于未使用 systemd 的系统,可直接检索 /var/log/messages 中的内核日志记录:
grep -i "oom\\|killed process" /var/log/messages
以上方式,如果输出中包含 invoked oom-killerKilled process,则说明发生了 OOM 事件。

方法四:查看系统内存状态(辅助)

除了排查日志,还可通过以下命令查看当前系统的内存使用情况,辅助判断是否存在内存压力:
# 查看系统整体内存使用概况(总量/已用/可用/缓存)
free -h

# 查看详细内存信息(对应 OOM 日志中的 Mem-Info 字段)
cat /proc/meminfo

# 实时监控内存变化(每秒刷新,共 5 次)
vmstat 1 5

# 查看 RSS(物理内存占用)最高的进程
ps aux --sort=-%mem | head -20

OOM 日志逐段解读

以下基于一条真实的 TencentOS Server OOM 日志,逐段解读各字段含义。

第一段:触发信息

Aug 2 00:55:46 VM-223-103-tlinux kernel: bkmonitorbeat invoked oom-killer: gfp_mask=0x14201ca(GFP_HIGHUSER_MOVABLE|__GFP_COLD), nodemask=(null), order=0, oom_score_adj=0
本例值
字段
含义
bkmonitorbeat
进程名
触发 OOM Killer 的进程名称(调用者,非被杀进程)
0x14201ca
gfp_mask
内存分配标志,括号内为可读形式。GFP_HIGHUSER_MOVABLE 表示申请高端用户态可移动页
(null)
nodemask
NUMA 节点掩码,限制从哪些节点分配内存。null 表示不限制
0
order
申请的页面阶数。0 = 1 个页面(4KB),1 = 2 个页面(8KB),以此类推
0
oom_score_adj
OOM 评分调整值,范围 -1000~1000。正值增加被杀概率,负值降低
注意:
nodemask 是 NUMA 概念,cpuset.mems_allowed 是 cpuset 概念,两者功能类似但来源不同。即使 nodemask=null,进程仍可能被 cpuset 限制在特定 NUMA 节点上。

第二段:进程上下文

Aug 2 00:55:46 VM-223-103-tlinux kernel: bkmonitorbeat cpuset=collector-bkmonitorbeat-62c1e40fc0a151a2d1796808a16b083c mems_allowed=0
Aug 2 00:55:46 VM-223-103-tlinux kernel: CPU: 15 PID: 14566 Comm: bkmonitorbeat Not tainted 4.14.105-1-tlinux3-0023 #1
Aug 2 00:55:46 VM-223-103-tlinux kernel: Hardware name: Tencent Cloud CVM, BIOS seabios-1.9.1-qemu-project.org 04/01/2014
各项参数说明如下:
本例值
字段
含义
collector-bkmonitorbeat-...
cpuset
进程所在的 cgroup cpuset 路径
0
mems_allowed
允许使用的 NUMA 节点。0 表示只能在 node 0 分配内存
15
CPU
触发时所在的 CPU 核心
14566
PID
进程 ID
4.14.105-1-tlinux3-0023
内核版本
当前运行的内核版本
Tencent Cloud CVM
Hardware
硬件信息
说明:
TencentOS Server 3 的 OOM 日志格式在不同内核版本间基本一致,而 TencentOS Server 4 字段会更多(如 writependingshmem_thp 等),但解读方法相同。

第三段:内核调用栈与寄存器

Aug 2 00:55:46 VM-223-103-tlinux kernel: Call Trace:
Aug 2 00:55:46 VM-223-103-tlinux kernel: dump_stack+0x63/0x8a
Aug 2 00:55:46 VM-223-103-tlinux kernel: dump_header+0x9f/0x204
Aug 2 00:55:46 VM-223-103-tlinux kernel: oom_kill_process+0x22c/0x440
Aug 2 00:55:46 VM-223-103-tlinux kernel: out_of_memory+0x114/0x4a0
Aug 2 00:55:46 VM-223-103-tlinux kernel: __alloc_pages_slowpath+0x837/0xab5
Aug 2 00:55:46 VM-223-103-tlinux kernel: __alloc_pages_nodemask+0x236/0x2a0
Aug 2 00:55:46 VM-223-103-tlinux kernel: alloc_pages_current+0x6a/0xb0
...
调用栈展示了 OOM Killer 的触发路径:


第四段:Mem-Info 内存概况

查看 mem-info 指令:
# 查看系统内存详情(对应 Mem-Info 中的各字段)
cat /proc/meminfo


# 查看 Slab 缓存使用情况
cat /proc/slabinfo | head -5


# 查看各 NUMA 节点内存分布
cat /sys/devices/system/node/node*/meminfo | grep -i "active\\|free\\|slab"
输出示例:
Aug 2 00:55:46 VM-223-103-tlinux kernel: Mem-Info:
active_anon:16087067
inactive_anon:27297
active_file:1083
inactive_file:913
unevictable:0
dirty:1
writeback:0
slab_reclaimable:49598
slab_unreclaimable:29114
mapped:3640
shmem:68701
pagetables:46710
free:73341
free_pcp:2500
free_cma:0
说明:数值以 page 为单位,x86 架构下 1 page = 4 KB。可用 getconf PAGE_SIZE 查看页面大小。
各项参数说明如下:
字段
本例值(页)
换算
含义
active_anon
16,087,067
~61.3 GB
活跃匿名内存(进程堆/栈等),OOM 分析重点关注项
inactive_anon
27,297
~107 MB
非活跃匿名内存
active_file
1,083
~4.2 MB
活跃文件缓存(文件页)
inactive_file
913
~3.6 MB
非活跃文件缓存,可回收
slab_reclaimable
49,598
~194 MB
可回收的 Slab 缓存(dentry/inode 等)
slab_unreclaimable
29,114
~114 MB
不可回收的 Slab 缓存
shmem
68,701
~268 MB
共享内存(tmpfs/shmem)
pagetables
46,710
~183 MB
页表占用
free
73,341
~286 MB
空闲页
本例分析active_anon 占 61.3 GB ,占比最高,说明匿名内存(进程堆)消耗了绝大部分内存,远超系统可回收能力,直接导致 OOM。

第五段:各 NUMA 节点与 zone 详情

Aug 2 00:55:46 VM-223-103-tlinux kernel: Node 0 Normal: free:32000kB min:30980kB low:93628kB high:156276kB ...
重点关注 freelow 的关系:
zone
free
low
判断
DMA
15,876 kB
16 kB
正常
DMA32
246,028 kB
4,096 kB
正常
Normal
32,000 kB
93,628 kB
free 低于 low,触发 OOM 的直接原因
当 zone 的 free 低于 low 水位线时,内核认为该 zone 内存严重不足,触发 OOM Killer。

第六段:buddyinfo 内存碎片化情况

Aug 2 00:55:46 VM-223-103-tlinux kernel: Node 0 Normal: 1480*4kB (UME) 678*8kB (UME) 574*16kB (UME) 193*32kB (UME) 86*64kB (UM) 10*128kB (UM) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 33488kB
buddyinfo 展示各阶空闲页面的分布。本示例 Normal zone 虽然 free 总量有 33 MB,但全是 4KB~128KB 的小块,没有 256KB 以上的连续大页,说明内存碎片化严重。虽然碎片化本身不是 OOM 的直接原因(order=0 只需 4KB),但碎片化会加剧高阶分配的失败率。

第七段:大页信息

Aug 2 00:55:46 VM-223-103-tlinux kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
本示例未配置大页,hugepages_total=0

常见 OOM 原因与排查方向

原因
特征
排查命令
进程内存泄漏
active_anon 持续增长不回落
top/ps aux --sort=-rss 找 RSS 最高的进程
cgroup 内存限制
日志含 memory.max 或 cgroup 路径
cat /sys/fs/cgroup/<path>/memory.max
Slab 缓存膨胀
slab_unreclaimable 异常大
cat /proc/slabinfoslabtop
共享内存过量
shmem 数值大
ipcs -m 查看共享内存段
内存碎片化
buddyinfo 高阶页面为 0
cat /proc/buddyinfo

预防与调优

调整进程 OOM 优先级

保护关键进程不被 OOM Killer 杀死:
# 降低被杀概率(-1000 等于完全禁止 OOM 杀死该进程)
echo -1000 > /proc/<pid>/oom_score_adj

# 永久设置(写入 systemd service) 在 [Service] 段添加:OOMScoreAdjust=-100

使用 cgroup 限制内存

防止单个进程消耗过多内存:
# cgroup v2 示例:限制进程最大内存为 4GB
mkdir /sys/fs/cgroup/myapp
echo 4G > /sys/fs/cgroup/myapp/memory.max
echo <pid> > /sys/fs/cgroup/myapp/cgroup.procs

配置 swap

适当配置 swap 可以在物理内存不足时提供缓冲(不推荐对性能敏感场景使用大 swap):
# 查看 swap 状态
swapon --show
free -h

升级实例规格

当业务负载确实超出当前实例的内存容量,且无法通过应用层优化(如修复内存泄漏、调整缓存策略)解决时,可考虑升级实例规格以增加可用内存:
# 查看当前实例内存规格
free -h

# 查看内核识别的物理内存总量
grep MemTotal /proc/meminfo
在腾讯云控制台或通过 API 调整实例规格时,建议注意以下事项:
升级实例规格通常需要重启实例,请提前做好业务切换和应急预案。
部分实例类型支持在线变配(无需停机),具体支持的类型以云服务器产品文档为准。
升级前建议先排查是否存在内存泄漏或配置不当,避免仅通过扩容掩盖问题。

监控告警

建议对以下指标设置告警:
可用内存低于总内存 10%
oom-killer 事件出现次数 > 0
进程 RSS 接近系统内存总量
# 快速检查是否曾有 OOM 事件
dmesg -T | grep -c "oom-killer"

附录:完整 OOM 日志样本

以下为本文档分析使用的完整日志,供参考:
Aug 2 00:55:46 VM-223-103-tlinux kernel: bkmonitorbeat invoked oom-killer: gfp_mask=0x14201ca(GFP_HIGHUSER_MOVABLE|__GFP_COLD), nodemask=(null), order=0, oom_score_adj=0
Aug 2 00:55:46 VM-223-103-tlinux kernel: bkmonitorbeat cpuset=collector-bkmonitorbeat-62c1e40fc0a151a2d1796808a16b083c mems_allowed=0
Aug 2 00:55:46 VM-223-103-tlinux kernel: CPU: 15 PID: 14566 Comm: bkmonitorbeat Not tainted 4.14.105-1-tlinux3-0023 #1
Aug 2 00:55:46 VM-223-103-tlinux kernel: Hardware name: Tencent Cloud CVM, BIOS seabios-1.9.1-qemu-project.org 04/01/2014
Aug 2 00:55:46 VM-223-103-tlinux kernel: Call Trace:
Aug 2 00:55:46 VM-223-103-tlinux kernel: dump_stack+0x63/0x8a
Aug 2 00:55:46 VM-223-103-tlinux kernel: dump_header+0x9f/0x204
Aug 2 00:55:46 VM-223-103-tlinux kernel: oom_kill_process+0x22c/0x440
Aug 2 00:55:46 VM-223-103-tlinux kernel: out_of_memory+0x114/0x4a0
Aug 2 00:55:46 VM-223-103-tlinux kernel: __alloc_pages_slowpath+0x837/0xab5
Aug 2 00:55:46 VM-223-103-tlinux kernel: __alloc_pages_nodemask+0x236/0x2a0
Aug 2 00:55:46 VM-223-103-tlinux kernel: alloc_pages_current+0x6a/0xb0
Aug 2 00:55:46 VM-223-103-tlinux kernel: __page_cache_alloc+0x6b/0xa0
Aug 2 00:55:46 VM-223-103-tlinux kernel: filemap_fault+0x3a6/0x640
Aug 2 00:55:46 VM-223-103-tlinux kernel: ext4_filemap_fault+0x31/0x50
Aug 2 00:55:46 VM-223-103-tlinux kernel: __do_fault+0x38/0xb0
Aug 2 00:55:46 VM-223-103-tlinux kernel: __handle_mm_fault+0xcc1/0x1030
Aug 2 00:55:46 VM-223-103-tlinux kernel: handle_mm_fault+0xd1/0x1e0
Aug 2 00:55:46 VM-223-103-tlinux kernel: __do_page_fault+0x200/0x500
Aug 2 00:55:46 VM-223-103-tlinux kernel: do_page_fault+0x32/0x100
Aug 2 00:55:46 VM-223-103-tlinux kernel: async_page_fault+0x45/0x50
Aug 2 00:55:46 VM-223-103-tlinux kernel: RIP: 0033:0x923425
Aug 2 00:55:46 VM-223-103-tlinux kernel: RSP: 002b:00007f0d30257d80 EFLAGS: 00010202
Aug 2 00:55:46 VM-223-103-tlinux kernel: RAX: 00000000000038e4 RBX: 000000c0003fa600 RCX: 0000000000962d67
Aug 2 00:55:46 VM-223-103-tlinux kernel: Mem-Info:
Aug 2 00:55:46 VM-223-103-tlinux kernel: active_anon:16087067 inactive_anon:27297 active_file:1083 inactive_file:913 unevictable:0 dirty:1 writeback:0 slab_reclaimable:49598 slab_unreclaimable:29114 mapped:3640 shmem:68701 pagetables:46710 free:73341 free_pcp:2500 free_cma:0
Aug 2 00:55:46 VM-223-103-tlinux kernel: Node 0 Normal: free:32000kB min:30980kB low:93628kB high:156276kB active_anon:61887756kB inactive_anon:109188kB present:63963136kB managed:62648408kB
Aug 2 00:55:46 VM-223-103-tlinux kernel: Node 0 DMA: 1*4kB (U) 0*8kB 0*16kB 0*32kB 2*64kB (U) 1*128kB (U) 1*256kB (U) 0*512kB 1*1024kB (U) 1*2048kB (M) 3*4096kB (M) = 15876kB
Aug 2 00:55:46 VM-223-103-tlinux kernel: Node 0 DMA32: 3673*4kB (UME) 2532*8kB (UME) 1204*16kB (UE) 1630*32kB (UME) 941*64kB (UME) 414*128kB (UME) 84*256kB (ME) 5*512kB (UME) 0*1024kB 1*2048kB (H) 0*4096kB = 245700kB
Aug 2 00:55:46 VM-223-103-tlinux kernel: Node 0 Normal: 1480*4kB (UME) 678*8kB (UME) 574*16kB (UME) 193*32kB (UME) 86*64kB (UM) 10*128kB (UM) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 33488kB
Aug 2 00:55:46 VM-223-103-tlinux kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
说明:以上日志截取了关键段落,省略了部分寄存器和重复字段。完整日志可通过 dmesg 命令获取。