应直接解析 /proc/$pid/smaps 中所有 swap: 行求和(单位kb),才是进程真实已换出的swap量;top/htop的swap列仅为 virtual−rss 估算值,未汇总各内存映射区,且忽略共享页、mmap等场景,常严重偏低或为0。

直接看 /proc/$PID/smaps 里的 Swap: 行求和,才是进程真实已换出的 swap 量;只看 top 或 htop 的 SWAP 列、甚至 smem 的 swap 值,大概率偏低或为 0 —— 它们没正确汇总所有内存映射区的 Swap:。
为什么不能只用 top/htop 看 SWAP 列
top 和 htop 默认显示的 SWAP 字段,实际是 Virtual - RSS 的粗略估算(即“虚拟地址空间减去物理驻留页”),不是内核记录的真实换出量。它不区分是否真被写入 swap 设备,也不处理共享内存页、匿名映射、mmap 文件等复杂场景。
- 很多进程显示
SWAP: 0,但/proc/$PID/smaps里加总Swap:可能高达几百 MB -
htop的SWAP列在较新版本中已默认隐藏,需手动按F2 → Display Options → Swap启用,且仍不可信 - 内核线程(如
kthreadd)或容器 init 进程可能被错误计入,但它们根本不走用户态 swap 路径
怎么从 smaps 正确提取单个进程的 swap 占用
每个 /proc/$PID/smaps 文件中,Swap: 行可能出现多次(对应堆、栈、VDSO、共享库、mmap 区等),必须全部加总,单位是 KB。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 安全求和命令:
awk '/^Swap:/ {sum += $2} END {print sum+0}' /proc/1234/smaps,+0防止空输出时 awk 不打印 - 不要用
grep Swap /proc/1234/smaps | head -1 | awk '{print $2}'—— 这只取第一个匹配行,漏掉 90% 以上真实 swap - 注意权限:PID 1(
init)的smaps通常不可读,脚本中应跳过:[ "$pid" = "1" ] && continue - 若结果为 0,不代表没用 swap,可能是刚 fork 出来还没触发换出,或内核未回收旧页(见下文)
一行命令快速找出 top10 swap 占用进程
临时排查最实用的管道命令,已过滤干扰项、适配字段对齐、避免权限错误:
for i in /proc/[0-9]*; do [ -f "$i/smaps" ] || continue; pid=$(basename "$i"); [ "$pid" = "1" ] && continue; swap=$(awk '/^Swap:/ {sum += $2} END {print sum+0}' "$i/smaps" 2>/dev/null); [ "$swap" != "0" ] && comm=$(ps -p "$pid" -o comm= 2>/dev/null | tr -d '\n'); [ -n "$comm" ] && echo "$pid $swap $comm"; done | sort -k2 -nr | head -10 | awk '{printf "%-8s %8s KB %s\n", $1, $2, $3}'
- 用
/proc/[0-9]*替代ls /proc | grep ^[0-9],避开/proc/sys等伪目录报错 -
ps -p "$pid" -o comm=只取短命令名,避免路径过长破坏列对齐 - 内核线程的
comm通常是小写字母开头(如ksoftirqd/0),而用户进程多为大写或混合,可用grep -q '^[a-z]'过滤(但该命令已省略,因内核线程Swap:恒为 0) - 输出单位是 KB,不是 MB ——
/proc/swaps和swapon --show的Used也是 KB,保持一致才好比对
swap 高 ≠ 内存泄漏,关键看 si/so 和 MemAvailable
swap 占用高只是表象。真正要命的是频繁换入换出(si/so),以及可用内存持续枯竭(MemAvailable 接近 0)。
- 运行
vmstat 1 5,紧盯si(swap in)和so(swap out)两列:连续几秒 > 100 KB/s 就说明磁盘 I/O 正被 swap 拖垮 - 查
free -h第二行的available值 —— 如果还有 500MB+,哪怕Swap: used是 7.9G/8.0G,也未必是泄漏,可能是历史换出页未回收 - 执行
dmesg | tail -20,找Out of memory或Killed process—— 这才是 OOM 杀手启动的铁证,比任何 swap 数值都关键 - 如果
si/so长期为 0,但某个进程Swap:持续增长,那才值得用valgrind或gdb深挖(C/C++ 场景),Java 则优先看堆外内存和 direct buffer
最易被忽略的一点:swap 使用量是“已换出页”的快照,不是“换出速率”。一个进程可能占了 2GB swap,但过去一小时完全没换入换出 —— 它只是安静地躺在磁盘上,系统并不卡。盯数值不如盯变化,看总量不如看活跃度。










