ps是定位内存泄露初期最轻量可靠的工具,通过--sort=-rss按实际物理内存占用排序可发现rss持续缓慢上涨的进程,结合pmap、smem和watch进一步分析内存分布、共享干扰及变化趋势。

用 ps 按 RSS 排序看实时内存占用
内存泄露初期往往表现为某个进程的常驻内存(RSS)持续缓慢上涨,ps 是最轻量、最可靠的起点。它不依赖额外工具,所有 Linux 发行版原生支持,且避免了 top 类交互式命令可能引入的采样偏差。
执行这条命令即可按实际物理内存占用从高到低排列:
ps aux --sort=-%mem | head -n 10
注意:--sort=-%mem 排的是“占系统总内存百分比”,对定位大内存进程有效;但若想看绝对值(比如确认是否真在涨),改用 --sort=-rss 更直接:
ps aux --sort=-rss | head -n 10
-
rss单位是 KB,数值稳定增长是内存泄露的强信号 - 避免只看
%mem—— 小内存机器上一个 200MB 进程可能占 40%,但在 64GB 机器上才 0.3%,容易被忽略 - 如果进程名被截断(如 Java 应用显示为
java),加-w参数展开:ps auxw --sort=-rss | head -n 10
用 pmap 查单个进程的内存段分布
当 ps 锁定可疑进程(比如 PID 12345),下一步要确认是不是堆内存异常膨胀。这时候 pmap 比 /proc/PID/smaps 更直观,能一眼看出哪类内存块占得多。
运行:
pmap -x 12345 | tail -n 20
-x 输出三列:size(虚拟内存大小)、rss(常驻物理内存)、dirty(脏页)。重点关注 rss 列中反复出现的大块(比如多个 50MB+ 的匿名映射)。
- Java 进程若看到大量
[ anon ]行且rss累加远超-Xmx设置值,大概率是 native memory 泄露(如 JNI、DirectByteBuffer) - Python 进程若
[heap]段 RSS 持续上涨,而对象计数没明显变化,可能是 C 扩展模块未释放内存 - 不要依赖
pmap -d(显示 dirty 页)—— 它在多数内核版本中不可靠,-x更稳
用 smem 看 PSS 消除共享内存干扰
多个进程共用同一动态库或 mmap 文件时,rss 会重复计算,导致总量虚高、单个进程排名失真。smem 的 pss(Proportional Set Size)按共享页均摊,更适合判断“真实贡献”。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
安装后执行:
smem -s pss -r | head -n 10
输出中 PSS 列单位是 KB,数值比 RSS 小,但加总后更接近系统真实物理内存占用。
- 若某进程
RSS很高但PSS很低,说明它只是“搭便车”用了大量共享内存,不是泄露源 - Java 应用常因使用相同 JDK 而在
rss中虚高,pss能快速排除这类干扰 -
smem需要 root 权限读取/proc/*/smaps,普通用户执行会跳过部分进程,看到的排行不完整
用 watch 持续观察 RSS 变化趋势
内存泄露不是静态快照能抓到的,必须看变化。用 watch 定期刷新 ps 是最简单有效的手段,比写脚本或开 top 更聚焦。
例如每 3 秒刷新一次 RSS 排行:
watch -n 3 'ps aux --sort=-rss | head -n 10'
关键是要盯住目标进程的 RSS 值是否单调递增,尤其注意“小步慢涨”—— 每分钟涨几 MB,几小时后就吃光内存。
- 别用
watch -n 1—— 频繁采样本身会增加系统负载,还可能掩盖真实增长节奏 - 如果发现某进程 RSS 在波动(涨一点又掉一点),先检查是否触发了 GC 或缓存淘汰,不是所有上涨都等于泄露
- 终端窗口太窄会导致字段换行,误判数据位置;确保终端宽度 >120 字符再执行
真正难的不是找到哪个进程在吃内存,而是确认它为什么吃——rss 上涨只是表象,背后可能是未关闭的文件描述符、反复 mmap 未 munmap、或者语言运行时自身的管理缺陷。定位到这里,才刚踩进问题的边界。










