前面我们介绍了Linux内核SLUB调试功能,现在我们来介绍一下slabinfo等相关的工具,这对于理解并调试slab缓存功能很有帮助。
slabinfo介绍
slabinfo 不是普通系统命令,而是内核源码自带的官方调试工具。
它的源码位于内核源码树的tools/mm/slabinfo.c,由内核社区直接维护,数据直接取自内核 SLUB 分配器,精准度远高于第三方脚本,是排查内核内存问题的强大工具。
编译与一键部署
slabinfo 无需复杂配置,进入内核源码目录即可编译:
cd /path/to/linux-xxx/tools/mmmake
为了方便全局调用,建议做一个软链接:
sudo ln -s /path/to/linux-xxx/tools/vm/slabinfo /usr/bin/slabinfo
运行的三个前提
必须用 root 权限(涉及内核内存、sysfs 伪文件操作);
内核需开启CONFIG_SLUB_DEBUG=y(主流发行版内核默认已开启);
进阶调试功能,需内核启动参数添加slub_debug=xxx。
slabinfo字段解读
直接运行sudo slabinfo,看到的每一列都是 slab 缓存的核心数据,搞懂这些是排查的基础:
Name Objects Objsize Space Slabs/Part/Cpu O/S O %Fr %Ef FlgAcpi-Namespace 510 48 24.5K 1/0/5 85 0 0 99Acpi-Operand 952 72 69.6K 4/0/13 56 0 0 98Acpi-Parse 949 56 53.2K 0/0/13 73 0 0 99Acpi-ParseExt 663 80 53.2K 0/0/13 51 0 0 99Acpi-State 663 80 53.2K 0/0/13 51 0 0 99AF_VSOCK 350 1224 458.7K 1/0/13 25 3 0 93 A...kmalloc-128 5856 128 749.5K 138/0/45 32 0 0 100kmalloc-16 6889 16 114.6K 5/3/23 256 0 10 96kmalloc-192 8253 192 1.6M 290/0/103 21 0 0 98kmalloc-1k 1852 1024 1.9M 28/4/31 32 3 6 98kmalloc-256 6769 256 1.8M 183/32/38 32 1 14 95kmalloc-2k 998 2048 2.0M 30/5/34 16 3 7 97kmalloc-32 6512 32 208.8K 18/4/33 128 0 7 99
Name:slab 缓存名称(如 kmalloc-32);
Objects:当前已分配的对象数量;
Objsize:单个对象的大小(字节);
Space:该缓存占用的总内核内存;
Slabs/Part/Cpu:满 slab / 部分空闲 slab / 每 CPU 缓存 slab 数量;
O/S:每个 slab 包含的对象数;
O:页分配器阶数(2^order 为分配的页块大小);
%Fr:缓存空闲内存占比;
%Ef:内存使用效率;
Flg:slab 标志位(快速记忆:* 别名、dDMA、A 缓存对齐、P 中毒、Z 红区、F 完整性检查)。
slabinfo 核心参数
不用死记硬背所有参数,生产排查只需要掌握高频场景参数,随用随查:
查看完整 slab 列表
默认只显示有数据的 slab,空缓存会被隐藏:
定位高内存占用(最常用)
排查内核内存上涨,第一步就是找 “内存大户”:
-S会按总内存占用降序排列,自带人类可读单位,搭配head直接看 Top10 高占用缓存。
排查内存碎片
slab 采用 “最佳匹配” 分配,会产生内部碎片,-L参数按内存浪费量排序:
比如申请 100 字节,内核会用 kmalloc-128 缓存,浪费 28 字节,这个参数能精准揪出碎片大户。
OOM :不可回收 slab 筛选
很多生产 OOM 的元凶,是不可回收 slab 占满内存,-U参数就是为这个场景而生(内核 4.15 + 支持):
这个参数源于一次真实生产故障:不可回收 slab 耗尽内存,OOM 杀手无进程可杀,直接宕机。排查 OOM 必用。
深度详情 + 正则筛选
想深挖某类缓存,用-r输出详细统计,支持正则匹配:
开启 SLUB_DEBUG 后,还能看到分配 / 释放的代码来源,定位泄漏点事半功倍。
陌生缓存快速识别
遇到不认识的 slab 名,用-a查看别名,直接知道它缓存哪种内核对象:
全局汇总统计
进阶调试:slabinfo 搞定内存损坏
slabinfo 不止能看统计,还能直接做slab 内存调试,专门解决内存越界、双重释放、内存损坏等硬核问题。
先开启内核调试参数
在 GRUB 启动参数中添加:
F:开启 slab 完整性检查;
Z:添加内存红区,防越界;
P:slab 中毒,释放后填充毒页;
U:追踪用户态关联 slab。
动态调试:-d 参数
无需重启,直接通过 slabinfo 开启 / 关闭调试:
sudo slabinfo --debug=FZPU # 开启调试sudo slabinfo -d # 关闭调试
底层通过操作/sys/kernel/slab/<缓存名>/伪文件实现,安全无侵入。
内存校验:-v 参数
怀疑内核 slab 内存损坏?用-v做完整性校验:
内核会遍历所有 slab 对象,检查元数据有效性,结果输出到内核日志,可以准确查出内存损坏问题。
其他配套工具:slabtop & slabratetop
除了 slabinfo,这两个实时工具能 complement 排查能力:
slabtop:类 top 实时监控
和系统 top 一样,实时刷新 slab 占用状态,默认按对象数排序:
适合实时观察 slab 变化,快速定位高频分配缓存。
slabratetop(eBPF):实时分配速率
这是 eBPF 时代的新利器,直接追踪内核 slab 分配速率:
sudo slabratetop-bpfcc 5 3
5 秒刷新一次,显示 3 次,底层追踪kmem_cache_alloc,精准看内核态分配速度和字节数,比传统工具更灵敏。
操作实例:谁在吃掉内核 slab 内存?
下面用一个真实排障流程,教你定位内核态内存占用元凶。
场景
服务器内核 slab 内存持续上涨,用户态进程无异常,系统负载缓慢升高。
步骤 1:定位高消耗缓存
用slabratetop找到分配最频繁的缓存:
输出显示:vm_area_struct缓存每秒分配 176 次,字节数居高不下。
步骤 2:追踪内核调用栈
用 kprobe 抓取分配内核栈:
sudo kprobe-perf -s 'p:kmem_cache_alloc name=+0(+96(%di)):string' | grep -A10 "vm_area_struct"
结果
清晰看到调用链:sys_brk() → do_brk() → do_brk_flags() → vm_area_alloc() → kmem_cache_alloc()
根因:进程频繁调用brk()扩张内存,内核持续分配 VMA 结构体,导致 slab 内存上涨。针对性优化进程内存管理策略后,问题解决。
slab 内存清零防护
最后补一个生产安全配置,防止 slab 内存数据泄露:在内核启动参数中添加:
init_on_alloc=1 init_on_free=1
slab 对象分配 / 释放时自动清零,提升内核安全性,仅带来轻微性能损耗,安全敏感型业务建议开启。