Linux 内存明明够用,OOM killer 还是杀进程?先看这三处
【摘要】 一句话结论: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 总量,容易误判。
建议的排查顺序
- 先读内核日志,确认哪一次 OOM、哪个进程被杀、order 与分区。
- 对照同一时间点,看
free、cgroup 限额和 Slab 的变化。 - 三处都排除了,再怀疑应用内存泄漏。顺序反了,很容易走弯路。
容易踩的坑
- 只看
MemFree,不看MemAvailable与Committed_AS。 - 把
buff/cache当成“被占用”,其实其中大部分是可以回收的。 - 在容器里看
free:看到的是宿主机内存,不是容器的限额。 - 盲目调整
vm.overcommit_memory或者关闭 OOM killer:可能只是把问题推迟、放大,生产环境要慎重。
小结
内存够不够,不能只看一个数字。先看分配失败的 order、水位与分区,再看 cgroup 限额,最后看 Slab 与页表。三处查完,问题往往就定位了一大半。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)