Linux命令-slabtop(实时显示内核 slab 缓存信息)
- 🔰 简介
- 📖 语法
- ⚙️ 选项
- 💡 实战示例
- 示例 1:基本 slabtop
- 示例 2:按对象数排序
- 示例 3:一次性输出 + 监控
- 示例 4:诊断内核内存泄漏
- 示例 5:常见 cache 名称识别
- 示例 6:与用户态内存工具对比
- 示例 7:性能调优场景
- 示例 8:自动化分析与脚本
- ⚠️ 注意事项
- 📝 总结
- 📚 相关命令
快速参考slabtop是实时显示 Linux 内核 slab 分配器缓存使用情况的工具,类似top但专门针对内核态内存(slab / slub / slob 三种分配器之一)。它显示各种内核对象的缓存命中率、对象数、占用内存,是诊断内核内存泄漏、内存碎片、驱动 bug的核心工具。用户态top看进程内存,slabtop看内核内存。
🔰 简介
| 项目 | 说明 |
|---|---|
| 命令全称 | slab top |
| 所属包 | procps-ng |
| 数据源 | /proc/slabinfo |
| 工作模式 | 实时刷新(默认 3 秒),或一次性输出 |
| 用途 | 诊断内核态内存问题 |
| 权限 | 需要 root(部分内核版本普通用户可见但不全) |
| 现代替代 | slabtop(命令本身)cat /proc/slabinfo(原始数据)perf / bpftool(高级诊断) |
slab / slub / slob 三种分配器:
| 分配器 | 特点 | 用途 |
|---|---|---|
slab | 原始实现,复杂 | 早期内核 |
slub | 简化版,Linux 默认 | 大多数发行版 |
slob | 极简版(Simple List of Blocks) | 嵌入式、小内存 |
slab 是什么:
- Linux 内核的小对象内存分配器(替代频繁的
kmalloc/kfree) - 预先为常见对象(
task_struct、inode、dentry、buffer_head等)建立对象池(cache) - 申请对象时从 cache 取,避免反复创建/销毁
- 解决内存碎片问题
📖 语法
slabtop[选项]⚙️ 选项
| 选项 | 简写 | 说明 |
|---|---|---|
--delay=N | -d N | 刷新间隔(秒),默认 3 |
--sort=SORT | -s SORT | 排序字段(见下表) |
--once | -o | 一次性输出(不刷新) |
--version | -V | 版本 |
--help | -? | 帮助 |
排序字段(-s 可选):
| 字段 | 含义 |
|---|---|
a | ACTIVE 对象数 |
b | 对象数/页(OBJ/SLAB) |
c | 缓存大小(CACHE SIZE) |
l | 命中次数(HITS) |
n | 名称(NAME) |
o | 活跃对象数 × 对象大小(活跃内存) |
p | 每页对象数 / 每 slab |
s | 对象大小(OBJ SIZE) |
u | 缓存使用率 |
💡 实战示例
示例 1:基本 slabtop
# 实时刷新(默认 3 秒)$sudoslabtop Active / Total Objects(% used):678901/1234567(55.0%)Active / Total Slabs(% used):23456/34567(67.9%)Active / Total Caches(% used):98/142(69.0%)Total / Used Memory:256789/145678OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME456783456775%0.50K12343749360K task_struct123451098789%0.13K4123016480K dentry123451000081%0.06K2006216000K kmalloc-649876789080%1.00K2465439440K inode8765700079%0.25K5671522680K kmalloc-256...字段详解:
| 字段 | 含义 |
|---|---|
OBJS | 该 cache 中总对象数 |
ACTIVE | 正在使用的对象数 |
USE | 使用率(ACTIVE/OBJS %) |
OBJ SIZE | 单对象大小 |
SLABS | 分配的 slab 页数 |
OBJ/SLAB | 每个 slab 含多少对象 |
CACHE SIZE | 该 cache 占用的总内存 |
NAME | cache 名(task_struct等) |
头部统计:
| 行 | 含义 |
|---|---|
Active / Total Objects | 活跃对象 / 总对象 |
Active / Total Slabs | 活跃 slab / 总 slab |
Active / Total Caches | 活跃 cache / 总 cache |
Total / Used Memory | 内存总量 / 使用量 |
示例 2:按对象数排序
# 按 OBJS 排序(看哪个 cache 对象最多)$sudoslabtop-sa# 按 CACHE SIZE 排序(看哪个 cache 占内存最多)$sudoslabtop-sc# 按 NAME 排序$sudoslabtop-sn# 按对象大小排序$sudoslabtop-ss# 实战:找出最大 cache$sudoslabtop-sc-o|head-20Active / Total Objects(% used):678901/1234567(55.0%)... OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME102400080000078%0.50K32768324096000K dentry50000040000080%1.00K12500402000000K inode20000015000075%0.25K20001001600000K kmalloc-256...# 重点关注:CACHE SIZE 大的 = 占用内存多示例 3:一次性输出 + 监控
# 一次性输出(不刷新)$sudoslabtop-o# 适合脚本处理# 监控 5 秒输出$sudoslabtop-d1-o# 每秒刷新一次# 录制到文件做趋势分析$sudoslabtop-d5-o>>/var/log/slab.log&# 持续 5 秒间隔输出# 配合 grep$sudoslabtop-o|grep-E"dentry|inode|task_struct"OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME456783456775%0.50K12343749360K task_struct123451098789%0.13K4123016480K dentry9876789080%1.00K2465439440K inode示例 4:诊断内核内存泄漏
# 场景:系统内存持续增长,怀疑内核泄漏# 1. 第一次记录$sudoslabtop-o>/tmp/slab_1.txt $date2024-01-1514:30:00# 2. 等待 5 分钟$sleep300# 3. 第二次记录$sudoslabtop-o>/tmp/slab_2.txt $date2024-01-1514:35:00# 4. 对比$diff/tmp/slab_1.txt /tmp/slab_2.txt# 找出增长最快的 cache# 例如:dentry 数量持续增长 = 文件系统相关驱动有问题# 例如:nf_conntrack 持续增长 = 防火墙连接表泄漏# 例如:vm_area_struct 持续增长 = 进程内存映射泄漏# 5. 实战:自动化监控$cat/opt/scripts/slab_monitor.sh#!/bin/bashLOG=/var/log/slab_growth.logTHRESHOLD=10000# 5 分钟增长阈值prev_count=0prev_name=""whiletrue;do# 取 cache 中最大 5 个output=$(slabtop-o|head-7|tail-5)# 提取最大 cachemax=$(echo"$output"|tail-1)name=$(echo"$max"|awk'{print $NF}')objs=$(echo"$max"|awk'{print $1}')# 检测增长if["$name"="$prev_name"]&&[$((objs-prev_count))-gt$THRESHOLD];thenecho"[$(date)] 警告:$name增长$((objs-prev_count))个对象">>$LOGlogger-pkern.warning"Slab cache$namegrowing:$objs"fiprev_name=$nameprev_count=$objssleep300done示例 5:常见 cache 名称识别
# ========== 1. 进程相关 ==========$sudoslabtop-o|grep-E"task_struct|signal|files_struct"# task_struct: 进程描述符(每个进程 1 个)# signal_struct: 信号结构# files_struct: 进程打开的文件# ========== 2. 文件系统相关 ==========$sudoslabtop-o|grep-E"dentry|inode|buffer_head"# dentry: 目录项(**最常见大对象**)# inode: 文件元数据# buffer_head: 文件页缓存# ========== 3. 网络相关 ==========$sudoslabtop-o|grep-E"sk_buff|sock|nf_conn"# sk_buff: 网络数据包(**网络性能关键**)# sock: 套接字# nf_conn: netfilter 连接追踪# ========== 4. 内存管理 ==========$sudoslabtop-o|grep-E"vm_area|page|mm_struct"# vm_area_struct: 进程的虚拟内存区# page: 内核页帧描述符# ========== 5. 驱动相关 ==========$sudoslabtop-o|grep-E"scsi|usb|kvm"# 各类驱动对象# ========== 实战:dentry 增长 = 目录项泄漏 ==========$sudoslabtop-sc-o|head-10OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME102400080000078%0.13K32768324096K dentry# 如果持续增长:# 1. 检查是否有进程持续打开/关闭目录# 2. 检查 NFS / FUSE 挂载# 3. 同步检查 /proc/sys/fs/dentry-state$cat/proc/sys/fs/dentry-state13456710987645000# nr_dentry / nr_unused / age_limit / ...# 手动清理$echo2>/proc/sys/vm/drop_caches# 释放 dentry + inode cache示例 6:与用户态内存工具对比
# ========== 1. 用户态 vs 内核态 ==========# 用户态:top / ps$top# 字段:VIRT(虚拟)/ RES(实际)/ SHR(共享)# 这些是**进程**的用户态内存# 内核态:slabtop$sudoslabtop# 字段:OBJS / SLABS / CACHE SIZE# 这些是**内核对象**的内存# ========== 2. 完整内存视图 ==========# 总览$free-htotal usedfreeshared buff/cache available Mem:7.7G1.2G4.0G 100M2.5G6.0G# total = 物理 RAM# used = 已用(用户 + 内核 + 缓存)# buff/cache = 内核页缓存(**会自动回收**)# available = **真正可用**(含可回收缓存)# 内核 slab 占多少?$sudoslabtop-o|head-1Active / Total Objects(% used):678901/1234567(55.0%)Total / Used Memory:256789/145678# Used Memory = 内核 slab 占用的内存# 用户态 + 内核态 = 完整内存占用# ========== 3. /proc/meminfo 详细信息 ==========$grep-E"Slab|SReclaimable|SUnreclaim"/proc/meminfo Slab:145678kB SReclaimable:87654kB ← 可回收的 slab SUnreclaim:58024kB ← 不可回收的 slab# SReclaimable + SUnreclaim = Slab# ========== 4. 完整内存全景图 ==========$cat/proc/meminfo|head-30MemTotal:8057892kB MemFree:4123456kB MemAvailable:6234567kB Buffers:123456kB Cached:2098765kB SwapCached:0kB Active:1234567kB Inactive:1876543kB Active(anon):456789kB Inactive(anon):123456kB Active(file):777778kB Inactive(file):1753087kB Unevictable:0kB Mlocked:0kB SwapTotal:2097148kB SwapFree:2097148kB Dirty:123kB Writeback:0kB AnonPages:580245kB Mapped:234567kB Shmem:123456kB KReclaimable:87654kB Slab:145678kB SReclaimable:87654kB SUnreclaim:58024kB KernelStack:5678kB PageTables:12345kB...示例 7:性能调优场景
# ========== 场景 1:网络服务器 sk_buff 增长 ==========# 表现:网卡丢包、网络延迟# 检查:$sudoslabtop-o|grep-E"sk_buff"OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME20000018000090%0.25K625032200000K skbuff_head_cache# 90% 使用率 = 接近上限,可能在网络高负载时丢包# 解决:# 1. 调整 netdev_max_backlog$sudosysctl-wnet.core.netdev_max_backlog=2000# 2. 调整 socket 缓冲区$sudosysctl-wnet.core.rmem_max=12582912$sudosysctl-wnet.core.wmem_max=12582912# ========== 场景 2:dentry 缓存不足 ==========# 表现:磁盘 IO 高、stat() 慢# 解决:调大 /proc/sys/vm/vfs_cache_pressure$cat/proc/sys/vm/vfs_cache_pressure100# 调小(保留更多 dentry)$sudosysctl-wvm.vfs_cache_pressure=50# ========== 场景 3:进程泄漏 task_struct ==========# 表现:进程数持续增长$ps-e|wc-l# 对应 slabtop 中 task_struct 增长# 解决:定位并 kill 泄漏进程$psaux--sort=-%mem|head-20# 找出大内存进程# ========== 场景 4:nf_conntrack 满 ==========$sudoslabtop-o|grepnf_conn OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME262144262144100%0.31K8192321048576K nf_conntrack# 100% 使用 = 防火墙连接表已满,新连接被拒绝# 解决:$sudosysctlnet.netfilter.nf_conntrack_max=524288$sudosysctlnet.netfilter.nf_conntrack_tcp_timeout_established=600# 调大连接上限 + 缩短超时示例 8:自动化分析与脚本
# ========== 1. slab 持续监控脚本 ==========$cat/opt/scripts/slab_watch.sh#!/bin/bash# 每 60 秒记录一次 slabtop 输出LOG_DIR=/var/log/slabmkdir-p$LOG_DIRwhiletrue;doTS=$(date+%F_%H%M%S)slabtop-o>"$LOG_DIR/slab_$TS.txt"# 清理 7 天前find$LOG_DIR-name"slab_*.txt"-mtime+7-deletesleep60done# ========== 2. 大 cache 告警 ==========$cat/opt/scripts/slab_alert.sh#!/bin/bash# 监控 cache > 1GBTHRESHOLD_KB=1048576# 1GBslabtop-o|tail-n+7|awk-vthresh=$THRESHOLD_KB' { cache_kb = $7 gsub("K", "", cache_kb) if (cache_kb > thresh) { print "[ALERT] " $8 " cache 使用 " cache_kb "K 内存" } }'|whilereadline;dologger-pkern.warning"Slab:$line"echo"$line"# 可加钉钉/邮件通知done# ========== 3. 与其他监控集成 ==========$cat/opt/scripts/slab_to_prometheus.sh#!/bin/bash# 转换 slabtop 为 prometheus 文本格式OUT=/var/lib/node_exporter/textfile/slab.promecho"# HELP slab_cache_bytes Total bytes used by kernel slab cache">$OUTecho"# TYPE slab_cache_bytes gauge">>$OUTslabtop-o|tail-n+7|awk' { cache_kb = $7 gsub("K", "", cache_kb) gsub("M", "000", cache_kb) cache_bytes = cache_kb * 1024 name = $8 gsub("-", "_", name) print "slab_cache_bytes{name=\"" name "\"} " cache_bytes }'>>$OUT# prometheus node_exporter 采集# 配合 grafana 画图⚠️ 注意事项
1. 需要 root 权限
普通用户执行slabtop会显示受限数据,仅当 kernel.yama.ptrace_scope=0 且/proc/slabinfo全员可读。生产中必须 sudo。
2. /proc/slabinfo 内核选项
部分内核配置CONFIG_SLAB关闭时/proc/slabinfo不存在。
检查:$cat/proc/slabinfo2>/dev/null|head# 无输出 = 内核不导出内核 < 2.6.32 或嵌入式系统可能没。
3. SLAB vs SLUB vs SLOB 输出差异
- SLUB(现代默认):字段最全
- SLAB(老内核):字段少
- SLOB(嵌入式):几乎无数据
现代 Linux 都是 SLUB。
4. 高频率刷新影响
slabtop -d 1每秒刷新,会持续读取/proc/slabinfo。
大量 cache(几万)时,读取可能10-50ms 延迟。
监控系统别用< 5 秒间隔。
5. 排序字段大小写
slabtop -s a(活跃对象数)和-s A(某些版本)含义不同。
用--sort=长格式更稳。
6. 名称中"-"的转义
很多 cache 名含-(kmalloc-64、nf_conn)。
grep/awk 处理时用引号或转义。
7. 与 /proc/meminfo 的关系
slabtop头部 “Used Memory” =/proc/meminfo中Slab字段。
但只展示部分(不是全部 cache)。
完整数据看/proc/slabinfo原始文件。
8. 容器内的局限
Docker 默认 PID 命名空间隔离,容器内slabtop看到的是宿主机全局。
也可能因 cgroup 限制看到不同视图。
9. 数值单位
slabtop默认千字节(K)。OBJ SIZE是单对象大小(带K)。
实际 K = 1024 字节,不是 1000。
10. 优化建议
如果某个 cache 持续 100% 满且不能回收:
- 检查驱动 bug(升级内核)
- 调整
/proc/sys/vm/*参数- 重启服务/系统(最后手段)
- 启用
slab_nomerge(避免误合并)- 使用 BPF 工具做精细分析
📝 总结
slabtop是"内核内存的 top"——专门看 slab 分配器。本节要点:
- 核心定位:用户态内存用
top/ps,内核态内存用slabtop - 关键字段:OBJS/ACTIVE/USE/OBJ SIZE/SLABS/CACHE SIZE/NAME
- 诊断场景:
- 内核内存增长 → 观察哪个 cache 在涨
- dentry 增长 → 目录项泄漏/缓存压力
- sk_buff 满 → 网络高负载
- nf_conntrack 满 → 防火墙拒绝连接
- 数据源:
/proc/slabinfo(slabtop是美化器) - 配合使用:
free(整体内存)/proc/meminfo(slab 详细)vmstat(slab 回收)ps(用户态进程内存)
最终建议:日常巡检
slabtop -s c -o看最大 5 个 cache;内存告警配合/proc/meminfo中 Slab 字段;深度诊断用perf/bpftool抓具体内核对象;生产监控导出 prometheus 指标。
📚 相关命令
| 命令 | 用途 |
|---|---|
slabtop | 实时 slab 信息(本节) |
top/htop | 用户态进程资源 |
free | 物理内存概览 |
cat /proc/slabinfo | slab 原始数据 |
cat /proc/meminfo | 详细内存信息 |
vmstat | 虚拟内存统计 |
ps aux | 进程详情 |
pmap | 进程内存映射 |
sysctl | 调整内核参数 |
echo N > /proc/sys/vm/drop_caches | 手动回收缓存 |
perf | 性能分析 |
bpftool | BPF 工具(高级) |
numastat | NUMA 内存统计 |
sysstat/sar -r | 内存历史 |
crash | 内核转储分析(vmcore) |