Linux 内存明明够用,OOM killer 还是杀进程?先看这三处

举报
1swei 发表于 2026/11/11 09:30:49 2026/11/11
【摘要】 一句话结论:free 显示的“可用内存”够用,不等于内核在分配内存的那一刻也够用。OOM killer 杀进程,通常是某条分配路径上先耗尽,而不是整机内存真的见底。 先分清三组数字free 的 available 是估算值,表示在不明显影响运行的前提下大概还能给应用多少内存。/proc/meminfo 里的 MemFree、MemAvailable、Slab、PageTables、Commi...

一句话结论:free 显示的“可用内存”够用,不等于内核在分配内存的那一刻也够用。OOM killer 杀进程,通常是某条分配路径上先耗尽,而不是整机内存真的见底。

先分清三组数字

  • free 的 available 是估算值,表示在不明显影响运行的前提下大概还能给应用多少内存。
  • /proc/meminfo 里的 MemFree、MemAvailable、Slab、PageTables、Committed_AS 各有含义,不能只盯其中一个。
  • 内核日志里的 OOM 记录会写明触发时的分区水位、分配阶数(order)和被杀的进程,先读它再下结论。

第一处:看分配阶数与水位,大块连续内存够不够

内核按 order 分配内存,order 越高,要的连续页就越多。内存碎片多了,即使 MemFree 总量看着不小,也可能凑不齐一块足够大的连续内存,高阶分配就会失败。

可以这样看:

cat /proc/buddyinfo
cat /proc/pagetypeinfo
dmesg -T | grep -i oom

如果日志里出现较高的 order,同时对应分区的空闲页很少,方向就比较明确:先考虑碎片和分配阶数,而不是直接认定应用泄漏。

第二处:看 cgroup 与服务限额,进程自己的“天花板”到了没有

容器和 systemd 服务都有各自的内存上限。宿主机还剩很多空闲内存,某个单元的限额到了,照样会触发 OOM。

可以这样看(cgroup v2 环境):

cat /sys/fs/cgroup/memory.max
cat /sys/fs/cgroup/memory.events
systemctl status <服务名>

memory.events 里的 oom_kill 计数能帮你确认这个 cgroup 是否真的触发过 OOM。systemd-cgtop 则适合横向比较各单元的用量,看看是谁先顶到上限。

第三处:看 Slab 与页表,内核结构占了多少

大量小文件、频繁创建销毁进程和线程,会让 dentry 缓存和页表持续增长,Slab 随之变大。这部分是内核自身占用的内存,不体现在某个应用进程的 RSS 里。

可以这样看:

grep -E 'Slab|SReclaimable|SUnreclaim|PageTables' /proc/meminfo
slabtop

注意区分:SReclaimable 是可以回收的部分,SUnreclaim 是暂时回收不了的部分。只看 Slab 总量,容易误判。

建议的排查顺序

  1. 先读内核日志,确认哪一次 OOM、哪个进程被杀、order 与分区。
  2. 对照同一时间点,看 free、cgroup 限额和 Slab 的变化。
  3. 三处都排除了,再怀疑应用内存泄漏。顺序反了,很容易走弯路。

容易踩的坑

  • 只看 MemFree,不看 MemAvailable 与 Committed_AS。
  • 把 buff/cache 当成“被占用”,其实其中大部分是可以回收的。
  • 在容器里看 free:看到的是宿主机内存,不是容器的限额。
  • 盲目调整 vm.overcommit_memory 或者关闭 OOM killer:可能只是把问题推迟、放大,生产环境要慎重。

小结

内存够不够,不能只看一个数字。先看分配失败的 order、水位与分区,再看 cgroup 限额,最后看 Slab 与页表。三处查完,问题往往就定位了一大半。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。