怎么定位
内核对象(slab)泄漏的排查路径是:先用 slabtop 找到持续增长的缓存,再读 /sys/kernel/slab/<cache>/objects 确认对象数是否单调上升,必要时借助 kmemleak 定位未释放的分配点。关键在于先区分可回收与不可回收——SReclaimable 部分在内存压力下会被释放,只有 SUnreclaim 或具体缓存的对象数持续增长,才构成泄漏的有力证据。
基本信息
| 总览 | sudo slabtop -o -s c(按缓存占用排序) |
|---|---|
| 单缓存对象数 | /sys/kernel/slab/<cache>/objects |
| 总量与构成 | /proc/meminfo 的 Slab、SReclaimable、SUnreclaim |
| 深度扫描 | kmemleak(需内核编译支持),报告在 /sys/kernel/debug/kmemleak |
| 权限 | 多数接口需 root |
| 容器环境 | 命名空间受限,需在宿主侧排查 |
典型使用场景
- 内存缓慢增长而进程 RSS 解释不了,转向内核侧取证
- 网络或存储负载长期运行后 dentry/inode 等缓存异常膨胀
- 容器频繁创建销毁后残留对象(cgroup、netns 相关缓存)增多
- 长时间运行的服务器定期核对 slab 总量作为健康检查项
- 为内核或驱动问题提供可复现的量化证据
排查步骤
排查步骤
sudo slabtop -o -s c | head -10 # 按占用大小排序,锁定可疑缓存
cat /sys/kernel/slab/dentry/objects # 单缓存对象数,间隔采样看是否单调增长
awk '/^(Slab|SReclaimable|SUnreclaim)/{print}' /proc/meminfo # 内核对象总量与可回收比例
mount | grep -q debugfs || sudo mount -t debugfs none /sys/kernel/debug # kmemleak 报告需要 debugfs
sudo cat /sys/kernel/debug/kmemleak 2>/dev/null | head # 需要内核开启 kmemleak 才有内容
echo scan | sudo tee /sys/kernel/debug/kmemleak # 触发一次扫描(有性能开销,慎用)指标读法
| 指标 | 含义 | 判读要点 |
|---|---|---|
| Slab | 内核对象总占用 | 作为总量基线 |
| SReclaimable | 压力下可释放的部分 | 增长本身不算泄漏 |
| SUnreclaim | 不可回收部分 | 持续增长是泄漏的主要嫌疑 |
| objects | 单个缓存的对象数量 | 间隔采样对比趋势,单调增长即异常 |
| slabtop 排序 | 各缓存占用对比 | 用于快速缩小候选范围 |
kmemleak 需要内核编译时开启并启用,运行时触发扫描会产生明显性能开销,生产环境应谨慎。它报告的是「疑似无法到达的内存」,仍需结合业务代码与复现路径确认。
slab 增长也可能来自正常业务变化:连接数、文件数、容器数增加都会带动对应缓存。判断泄漏要同时满足两点——对象数持续单调增长,且与业务量变化不匹配、负载回落后仍不释放。