Slab占用高不等于内存泄漏,但SUnreclaim持续增长且超总内存10%是强泄漏信号;需通过/proc/meminfo查Slab与SUnreclaim值,用slabtop -s -a定位OBJ/SLAB高且USE≈100%的不可回收缓存(如kmalloc-*),再验证其reclaim_account为0,方可确认泄漏源。

Slab 占用高 ≠ 内存泄漏,但 SUnreclaim 持续增长且占比超 10% 是强泄漏信号;真正要查的不是“有没有泄漏”,而是“哪个 slab 缓存正在吃掉不可回收内存”。
怎么看 Slab 总用量和不可回收部分
直接看 /proc/meminfo 最快:
cat /proc/meminfo | grep -E "^(Slab|SUnreclaim)"
输出类似:
Slab: 49115748 kB SUnreclaim: 48230124 kB
SUnreclaim 是关键——它代表 slab 中标记为不可回收的对象所占内存。如果这个值接近 Slab 总量(比如上例中占 98%),说明几乎全是不可回收缓存,极大概率存在泄漏。
-
SUnreclaim / Slab > 0.9:高度可疑,需立即下钻 -
SUnreclaim > 总内存 × 0.1(如 64G 机器 > 6.4G):已到风险阈值 - 注意:
Slab本身包含可回收部分(如 dentry、inode),不能单看它大就断定泄漏
怎么定位具体是哪个 slab 缓存占用了 SUnreclaim
用 slabtop -s -a 按活跃对象数排序,重点关注 OBJ/SLAB 高且 USE 接近 100% 的缓存:
slabtop -s -a
观察 NAME 列,比如:
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 123456 123456 100% 0.12K 2940 42 11760K kmalloc-128 78901 78901 100% 0.25K 3712 21 14848K kmalloc-256
这些 kmalloc-* 缓存若长期满载、不释放,就是重点怀疑对象。
- 别只信
slabtop的ACTIVE数——它反映的是当前被标记为“正在使用”的对象,但不等于“被谁持有” - 优先筛
kmalloc-*、ext4_*、nf_conntrack_*这类与驱动/文件系统/网络模块强相关的缓存名 - 对比历史数据:用
watch -n 30 'slabtop -s -a | head -15'持续观察 10 分钟,看哪些缓存的OBJS在稳定上涨
怎么确认某个 slab 是否真的不可回收
查对应缓存的 reclaim_account 文件:
cat /sys/kernel/slab/kmalloc-128/reclaim_account
返回 0 表示不可回收(即计入 SUnreclaim),返回 1 表示可回收(计入 Slab 但不计入 SUnreclaim)。
- 只有
reclaim_account == 0的 slab 才可能造成SUnreclaim持续增长 - 常见不可回收缓存:多数
kmalloc-*(内核通用分配)、task_struct、某些驱动私有缓存(如nvidia_*) - 可回收缓存如
dentry、inode即使占用大,系统空闲时也会自动回收,不构成泄漏
怎么进一步追根溯源(非 root 权限下能做的有限)
普通用户能做的止步于定位缓存名;真要定位到模块或驱动,需要 root + 工具链支持:
- 先用
lsmod看当前加载的模块,结合缓存名猜测(例如kmalloc-192异常 → 查是否有自研内核模块频繁调用kmalloc(192)) - 用
dmesg -T | grep -i "slab\|oom\|memory"看近期是否出现过 slab 相关警告或 OOM 日志 - 若有 crash 工具环境,可用
crash /proc/kcore加载符号后执行slabcache -v kmalloc-192查分配栈(但需调试符号) - 生产环境慎用
perf record -e kmem:kmalloc,kmempool_alloc -- sleep 30,开销大且需 root
最常被忽略的一点:kmalloc-* 缓存暴涨,往往不是应用层代码写的 bug,而是某个内核模块(尤其是闭源驱动)在异常路径下分配了内存却没释放——此时 /sys/kernel/slab/<name>/alloc_calls 和 free_calls 的差值会持续扩大,但普通用户看不到这两个文件,得靠运维或内核工程师介入。


















