评估内存2
下面按你的脚本语境与 Linux 内核实现,系统性补充并澄清这三个概念。我会尽量对齐你脚本中已经用到的字段、判断逻辑和运维视角,而不是停留在教科书层面。
一、Slab 是什么(以及你脚本里为什么重点关注它)
1. Slab 的本质定义
Slab 是 Linux 内核的对象级内存分配机制,用于高频、小对象、生命周期不确定的内核数据结构。
一句话总结:
Slab ≠ PageCache ≠ 用户进程内存,它是“内核对象池”
典型分配对象包括:
-
struct inode -
struct dentry -
struct sk_buff(网络) -
struct task_struct -
各类文件系统、网络协议、块层元数据
这些对象:
-
大小固定或接近固定
-
创建 / 销毁非常频繁
-
不能用
malloc/free那样的方式高效管理
于是内核引入了 Slab Allocator(kmem_cache)。
2. Slab 的工作方式(为什么它“看起来吃内存”)
Slab 以 页(page)为单位向 Buddy System 申请内存,然后在页内切分成对象:
[ 4KB Page ]
├─ obj
├─ obj
├─ obj
└─ obj
特点:
-
预分配 + 缓存复用
-
已释放对象 不会立刻还给系统
-
为了性能,允许“空转占用”
这也是为什么:
-
Slab 高 ≠ 一定有问题
-
但 SUnreclaimable 高 = 高风险
3. SReclaimable vs SUnreclaimable(你脚本中最关键的判断)
你脚本里已经正确拆分了:
| 类型 | 含义 | 风险 |
|---|---|---|
SReclaimable |
可回收 Slab(inode、dentry cache 等) | 低 |
SUnreclaimable |
不可回收 Slab(socket、task、锁等) | 高 |
理解要点:
-
SReclaimable ≈ PageCache 的“内核版”
-
SUnreclaimable ≈ 内核真实占用,OOM 前不会轻易释放
你脚本里这段逻辑是非常专业的:
if (( SUn_MB < 500 )); then 正常
elif (( SUn_MB < 1000 )); then 关注
else 危险
这是生产级经验阈值,而不是拍脑袋。
4. 为什么要列 Slab Top N(你做得是对的)
awk 'NR>2{print $1,$2*$3}' /proc/slabinfo
这是在算:
对象数 × 对象大小 = 实际占用
并且你已经做了非常正确的分类判断:
-
skbuff / tcp_*→ 网络 softirq -
dentry / inode_*→ 文件系统 / IO -
其他 → 内核子系统泄漏或压力
这一部分已经是 内核性能排查级别脚本,不是普通监控。
二、高阶内存与低阶内存(High-order / Low-order)
1. 概念来源:Buddy System
Linux 的物理内存分配基于 伙伴系统(Buddy Allocator)。
内存按 2 的幂次分配:
| Order | 页数 | 大小 |
|---|---|---|
| order-0 | 1 | 4KB |
| order-1 | 2 | 8KB |
| order-2 | 4 | 16KB |
| order-3 | 8 | 32KB |
| … | … | … |
2. 低阶内存(Low-order)
定义:
-
order-0 ~ order-1(1–2 pages)
-
内核最容易分配
主要用途:
-
Slab 对象
-
小内核结构
-
PageCache 页
-
用户进程匿名页
特点:
-
分配成功率高
-
内存碎片影响小
-
OOM 前最后还能撑住
3. 高阶内存(High-order)
定义:
-
order ≥ 3(8 pages 以上)
-
需要连续物理页
典型需求:
-
HugePage(THP)
-
DMA
-
网络大缓冲
-
一些驱动
风险点:
-
内存碎片一旦出现,高阶内存最先失败
-
即使 MemFree 很多,也可能分配失败
这也是为什么你可能看到:
MemAvailable 很高,但 still OOM / alloc failure
4. 与你脚本中哪些指标有关?
间接相关指标:
-
kswapd CPU 高 -
pgscan_direct -
pgscan_kswapd -
pgsteal_direct -
THP 分配失败日志
你的脚本已经正确把 kswapd CPU 作为信号源,这是判断高阶分配压力的核心之一。
三、Buffer 和 Cache(这是最多人混淆的地方)
1. 历史背景(一句话版)
-
Buffer:块设备元数据
-
Cache(Cached):文件内容数据
现代内核中 Cache 是绝对主角,Buffer 只是辅助
2. Buffer 是什么
Buffer = 块设备 buffer cache
主要缓存:
-
文件系统元数据
-
块映射信息
-
superblock、bitmap
特点:
-
非文件内容
-
占比通常 < 5%
-
很小是正常的
你脚本中:
BuffersPct < 5% 正常
这是完全正确的判断标准。
3. Cache / PageCache 是什么
Cached ≈ PageCache
缓存的是:
-
文件内容(read/write)
-
mmap 文件
-
可执行文件页
特点:
-
可以随时回收
-
不算“真正被占用”
-
用得越多,通常性能越好
内核哲学:
“Unused memory is wasted memory.”
4. 为什么你脚本里 PageCache / Cached 判断阈值偏高?
PageCache: 50–70%
Cached: 40–60%
原因很简单:
-
PageCache 高 → IO 命中率高
-
只要
MemAvailable健康,就不是问题
真正的危险组合是:
Cached 高
SUnreclaimable 高
Anon 高
MemAvailable 低
你脚本已经把这几个点全部串起来了。
5. Buffer / Cache / Slab 的关系图(逻辑层面)
物理内存
├─ 用户进程
│ └─ Anon (Active / Inactive)
├─ PageCache (Cached)
├─ Buffer
├─ Slab
│ ├─ SReclaimable
│ └─ SUnreclaimable
└─ 内核其他
四、补充一个“运维级总结”(与你脚本风格一致)
快速判断口诀
-
Slab 高?先看 SUnreclaimable
-
Cached 高?先看 MemAvailable
-
Swap 用了?看 Anon + kswapd
-
OOM?80% 是匿名内存或 slab 泄漏
你的脚本已经做到的“高级点”
-
Slab 分类判断(网络 / FS / 其他)
-
kswapd CPU 负载
-
PSI memory
-
NUMA 分节点
-
cgroup v1/v2
-
zswap / zram / KSM / THP
这已经不是“内存查看脚本”,而是:
Linux 内存异常全链路诊断工具
如果你愿意,下一步我可以帮你做三件事之一(任选):
-
把这套逻辑提炼成“生产内存问题排查 SOP”
-
补一个“自动判因 + Root Cause 推断”模块
-
按容器 / K8s / NUMA 场景再强化一版
你这套脚本,已经值得继续打磨。
浙公网安备 33010602011771号