Linux命令-slabtop(实时显示内核 slab 缓存信息)

Linux命令-slabtop(实时显示内核 slab 缓存信息)

    • [🔰 简介](#🔰 简介)
    • [📖 语法](#📖 语法)
    • [⚙️ 选项](#⚙️ 选项)
    • [💡 实战示例](#💡 实战示例)
      • [示例 1:基本 slabtop](#示例 1:基本 slabtop)
      • [示例 2:按对象数排序](#示例 2:按对象数排序)
      • [示例 3:一次性输出 + 监控](#示例 3:一次性输出 + 监控)
      • [示例 4:诊断内核内存泄漏](#示例 4:诊断内核内存泄漏)
      • [示例 5:常见 cache 名称识别](#示例 5:常见 cache 名称识别)
      • [示例 6:与用户态内存工具对比](#示例 6:与用户态内存工具对比)
      • [示例 7:性能调优场景](#示例 7:性能调优场景)
      • [示例 8:自动化分析与脚本](#示例 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_structinodedentrybuffer_head 等)建立对象池(cache)
  • 申请对象时从 cache 取避免反复创建/销毁
  • 解决内存碎片问题

📖 语法

bash 复制代码
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

bash 复制代码
# 实时刷新(默认 3 秒)
$ sudo slabtop

 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 / 145678

OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
45678 34567  75%    0.50K    1234      37       49360K task_struct
12345 10987  89%    0.13K     412      30       16480K dentry
12345 10000  81%    0.06K     200      62       16000K kmalloc-64
9876  7890   80%    1.00K    2465       4       39440K inode
8765  7000   79%    0.25K     567      15       22680K 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:按对象数排序

bash 复制代码
# 按 OBJS 排序(看哪个 cache 对象最多)
$ sudo slabtop -s a

# 按 CACHE SIZE 排序(看哪个 cache 占内存最多)
$ sudo slabtop -s c

# 按 NAME 排序
$ sudo slabtop -s n

# 按对象大小排序
$ sudo slabtop -s s

# 实战:找出最大 cache
$ sudo slabtop -s c -o | head -20
 Active / Total Objects (% used)    : 678901 / 1234567 (55.0%)
...
OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
  1024000  800000  78%    0.50K    32768      32      4096000K dentry
  500000  400000  80%    1.00K    12500      40      2000000K inode
  200000  150000  75%    0.25K    2000      100      1600000K kmalloc-256
  ...
# 重点关注:CACHE SIZE 大的 = 占用内存多

示例 3:一次性输出 + 监控

bash 复制代码
# 一次性输出(不刷新)
$ sudo slabtop -o
# 适合脚本处理

# 监控 5 秒输出
$ sudo slabtop -d 1 -o
# 每秒刷新一次

# 录制到文件做趋势分析
$ sudo slabtop -d 5 -o >> /var/log/slab.log &
# 持续 5 秒间隔输出

# 配合 grep
$ sudo slabtop -o | grep -E "dentry|inode|task_struct"
 OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
 45678 34567  75%    0.50K    1234      37       49360K task_struct
12345 10987  89%    0.13K     412      30       16480K dentry
 9876  7890   80%    1.00K    2465       4       39440K inode

示例 4:诊断内核内存泄漏

bash 复制代码
# 场景:系统内存持续增长,怀疑内核泄漏

# 1. 第一次记录
$ sudo slabtop -o > /tmp/slab_1.txt
$ date
2024-01-15 14:30:00

# 2. 等待 5 分钟
$ sleep 300

# 3. 第二次记录
$ sudo slabtop -o > /tmp/slab_2.txt
$ date
2024-01-15 14: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/bash
LOG=/var/log/slab_growth.log
THRESHOLD=10000   # 5 分钟增长阈值

prev_count=0
prev_name=""

while true; do
    # 取 cache 中最大 5 个
    output=$(slabtop -o | head -7 | tail -5)
    # 提取最大 cache
    max=$(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 ]; then
        echo "[$(date)] 警告: $name 增长 $((objs - prev_count)) 个对象" >> $LOG
        logger -p kern.warning "Slab cache $name growing: $objs"
    fi
    
    prev_name=$name
    prev_count=$objs
    sleep 300
done

示例 5:常见 cache 名称识别

bash 复制代码
# ========== 1. 进程相关 ==========
$ sudo slabtop -o | grep -E "task_struct|signal|files_struct"
# task_struct: 进程描述符(每个进程 1 个)
# signal_struct: 信号结构
# files_struct: 进程打开的文件

# ========== 2. 文件系统相关 ==========
$ sudo slabtop -o | grep -E "dentry|inode|buffer_head"
# dentry: 目录项(**最常见大对象**)
# inode: 文件元数据
# buffer_head: 文件页缓存

# ========== 3. 网络相关 ==========
$ sudo slabtop -o | grep -E "sk_buff|sock|nf_conn"
# sk_buff: 网络数据包(**网络性能关键**)
# sock: 套接字
# nf_conn: netfilter 连接追踪

# ========== 4. 内存管理 ==========
$ sudo slabtop -o | grep -E "vm_area|page|mm_struct"
# vm_area_struct: 进程的虚拟内存区
# page: 内核页帧描述符

# ========== 5. 驱动相关 ==========
$ sudo slabtop -o | grep -E "scsi|usb|kvm"
# 各类驱动对象

# ========== 实战:dentry 增长 = 目录项泄漏 ==========
$ sudo slabtop -s c -o | head -10
 OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
 1024000  800000  78%    0.13K   32768      32      4096K dentry
# 如果持续增长:
# 1. 检查是否有进程持续打开/关闭目录
# 2. 检查 NFS / FUSE 挂载
# 3. 同步检查 /proc/sys/fs/dentry-state
$ cat /proc/sys/fs/dentry-state
134567  109876  45 0  0  0
# nr_dentry  /  nr_unused  /  age_limit  /  ...

# 手动清理
$ echo 2 > /proc/sys/vm/drop_caches
# 释放 dentry + inode cache

示例 6:与用户态内存工具对比

bash 复制代码
# ========== 1. 用户态 vs 内核态 ==========

# 用户态:top / ps
$ top
# 字段:VIRT(虚拟)/ RES(实际)/ SHR(共享)
# 这些是**进程**的用户态内存

# 内核态:slabtop
$ sudo slabtop
# 字段:OBJS / SLABS / CACHE SIZE
# 这些是**内核对象**的内存

# ========== 2. 完整内存视图 ==========

# 总览
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           7.7G        1.2G        4.0G        100M        2.5G        6.0G
# total = 物理 RAM
# used = 已用(用户 + 内核 + 缓存)
# buff/cache = 内核页缓存(**会自动回收**)
# available = **真正可用**(含可回收缓存)

# 内核 slab 占多少?
$ sudo slabtop -o | head -1
 Active / 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:           145678 kB
SReclaimable:    87654 kB    ← 可回收的 slab
SUnreclaim:      58024 kB    ← 不可回收的 slab
# SReclaimable + SUnreclaim = Slab

# ========== 4. 完整内存全景图 ==========
$ cat /proc/meminfo | head -30
MemTotal:        8057892 kB
MemFree:         4123456 kB
MemAvailable:    6234567 kB
Buffers:          123456 kB
Cached:          2098765 kB
SwapCached:            0 kB
Active:          1234567 kB
Inactive:        1876543 kB
Active(anon):     456789 kB
Inactive(anon):   123456 kB
Active(file):     777778 kB
Inactive(file):  1753087 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       2097148 kB
SwapFree:        2097148 kB
Dirty:               123 kB
Writeback:             0 kB
AnonPages:        580245 kB
Mapped:           234567 kB
Shmem:            123456 kB
KReclaimable:      87654 kB
Slab:            145678 kB
SReclaimable:      87654 kB
SUnreclaim:        58024 kB
KernelStack:        5678 kB
PageTables:        12345 kB
...

示例 7:性能调优场景

bash 复制代码
# ========== 场景 1:网络服务器 sk_buff 增长 ==========
# 表现:网卡丢包、网络延迟
# 检查:
$ sudo slabtop -o | grep -E "sk_buff"
 OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
  200000  180000  90%    0.25K   6250      32       200000K skbuff_head_cache
# 90% 使用率 = 接近上限,可能在网络高负载时丢包

# 解决:
# 1. 调整 netdev_max_backlog
$ sudo sysctl -w net.core.netdev_max_backlog=2000
# 2. 调整 socket 缓冲区
$ sudo sysctl -w net.core.rmem_max=12582912
$ sudo sysctl -w net.core.wmem_max=12582912

# ========== 场景 2:dentry 缓存不足 ==========
# 表现:磁盘 IO 高、stat() 慢
# 解决:调大 /proc/sys/vm/vfs_cache_pressure
$ cat /proc/sys/vm/vfs_cache_pressure
100
# 调小(保留更多 dentry)
$ sudo sysctl -w vm.vfs_cache_pressure=50

# ========== 场景 3:进程泄漏 task_struct ==========
# 表现:进程数持续增长
$ ps -e | wc -l
# 对应 slabtop 中 task_struct 增长
# 解决:定位并 kill 泄漏进程
$ ps aux --sort=-%mem | head -20
# 找出大内存进程

# ========== 场景 4:nf_conntrack 满 ==========
$ sudo slabtop -o | grep nf_conn
 OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
  262144  262144 100%    0.31K   8192      32      1048576K nf_conntrack
# 100% 使用 = 防火墙连接表已满,新连接被拒绝

# 解决:
$ sudo sysctl net.netfilter.nf_conntrack_max=524288
$ sudo sysctl net.netfilter.nf_conntrack_tcp_timeout_established=600
# 调大连接上限 + 缩短超时

示例 8:自动化分析与脚本

bash 复制代码
# ========== 1. slab 持续监控脚本 ==========
$ cat /opt/scripts/slab_watch.sh
#!/bin/bash
# 每 60 秒记录一次 slabtop 输出
LOG_DIR=/var/log/slab
mkdir -p $LOG_DIR

while true; do
    TS=$(date +%F_%H%M%S)
    slabtop -o > "$LOG_DIR/slab_$TS.txt"
    # 清理 7 天前
    find $LOG_DIR -name "slab_*.txt" -mtime +7 -delete
    sleep 60
done

# ========== 2. 大 cache 告警 ==========
$ cat /opt/scripts/slab_alert.sh
#!/bin/bash
# 监控 cache > 1GB
THRESHOLD_KB=1048576  # 1GB

slabtop -o | tail -n +7 | awk -v thresh=$THRESHOLD_KB '
{
    cache_kb = $7
    gsub("K", "", cache_kb)
    if (cache_kb > thresh) {
        print "[ALERT] " $8 " cache 使用 " cache_kb "K 内存"
    }
}' | while read line; do
    logger -p kern.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.prom
echo "# HELP slab_cache_bytes Total bytes used by kernel slab cache" > $OUT
echo "# TYPE slab_cache_bytes gauge" >> $OUT

slabtop -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 不存在。

检查:

bash 复制代码
$ cat /proc/slabinfo 2>/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-64nf_conn)。

grep/awk 处理时用引号转义
7. 与 /proc/meminfo 的关系

slabtop 头部 "Used Memory" = /proc/meminfoSlab 字段。

只展示部分 (不是全部 cache)。

完整数据看 /proc/slabinfo 原始文件。
8. 容器内的局限

Docker 默认 PID 命名空间隔离,容器内 slabtop 看到的是宿主机全局

也可能因 cgroup 限制看到不同视图。
9. 数值单位

slabtop 默认千字节 (K)。

OBJ SIZE 是单对象大小(带 K)。

实际 K = 1024 字节,不是 1000
10. 优化建议

如果某个 cache 持续 100% 满且不能回收:

  1. 检查驱动 bug(升级内核)
  2. 调整 /proc/sys/vm/* 参数
  3. 重启服务/系统(最后手段)
  4. 启用 slab_nomerge(避免误合并)
  5. 使用 BPF 工具做精细分析

📝 总结

slabtop 是"内核内存的 top"------专门看 slab 分配器。本节要点:

  • 核心定位 :用户态内存用 top/ps内核态内存用 slabtop
  • 关键字段:OBJS/ACTIVE/USE/OBJ SIZE/SLABS/CACHE SIZE/NAME
  • 诊断场景
    • 内核内存增长 → 观察哪个 cache 在涨
    • dentry 增长 → 目录项泄漏/缓存压力
    • sk_buff 满 → 网络高负载
    • nf_conntrack 满 → 防火墙拒绝连接
  • 数据源/proc/slabinfoslabtop 是美化器)
  • 配合使用
    • 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)
相关推荐
蚰蜒螟3 小时前
从内核源码看Linux启动:chroot、execve与MS_MOVE的协奏曲
linux·服务器·网络
酷可达拉斯4 小时前
自动化运维-ansible配置文件与主机清单
linux·运维·自动化·ansible
影视飓风TIM4 小时前
Linux下C语言缓冲区原理 + Git版本控制
linux·c语言·git
来者皆善5 小时前
ZYNQ linux上使用 USB CDC ACM
linux·运维·服务器
Dawn-bit6 小时前
Linux磁盘分区与Swap和磁盘故障查询
linux·运维·服务器·网络·云计算
无足鸟ICT7 小时前
【RHCA+】$[]
linux·运维·服务器
运维技术小记8 小时前
国产化环境配置 VNC 远程桌面:麒麟 V10 实战
linux·运维·服务器
xiaoye-duck8 小时前
《Linux系统编程》Linux 系统多线程(八): C++ 高并发线程池全链路深度解析与从零手撕实现
linux·c++·线程池
寒水馨9 小时前
Linux下载、安装protobuf-v35.1(附安装包protoc-35.1-linux-x86_64.zip)
linux·运维·服务器·google·序列化·protobuf·protoc