ps aux --sort=-%mem 最快最稳,因其为一次性静态快照,不依赖交互、不刷新、不卡顿,适合脚本调用或远程批量检查;而 top 动态刷新易错过 rss 突增峰值。

直接看结论:内存利用率排行用 ps aux --sort=-%mem 最快最稳;找内存泄漏不能只盯进程 RSS,得结合 free -h 的 available 趋势、/proc/meminfo 中的 Slab 和 PageTables,再配合 slabtop 或 kmemleak 定位内核级泄漏。
ps aux --sort=-%mem 为什么比 top 更适合快速排查
它是一次性静态快照,不依赖交互、不刷新、不卡顿,适合脚本调用或远程批量检查。而 top 默认按 CPU 排序,按 M 切换后虽能看内存,但容易被动态刷新干扰判断——尤其当某个进程 RSS 突增又回落时,top 可能刚好错过峰值。
-
--sort=-%mem按物理内存占用百分比降序,+%mem是升序 -
rsz(即RSIZE)字段表示实际物理内存 KB 数,比%MEM更适合跨机器比较(避免因总内存不同导致百分比失真) - 加
| head -n 10只取前 10,避免输出过长;加| grep -v "java\|node"可临时过滤常见大内存应用,聚焦异常项 - 注意:
%MEM计算分母是总物理内存,不是available,所以即使系统已开始 OOM,该值也可能看起来“正常”
free -h 的 available 持续下降才是内存泄漏的第一信号
很多人盯着 used 或 free 列做判断,这是错的。Linux 的 cache/buffer 会自动回收,真正反映压力的是 available ——它代表当前可立即分配给新进程的内存。
- 如果
available在数小时/数天内稳定下滑(尤其伴随buff/cache不同步上升),基本可判定存在泄漏 -
free -h输出中若Swap used也在缓慢增长,说明物理内存已严重不足,内核开始换页,此时必须干预 - 不要用
cat /proc/meminfo | grep MemAvailable替代free -h:前者单位是 KB,且某些旧内核(如 3.10)不支持该字段,free会自动 fallback 到估算逻辑
slabtop 和 /proc/slabinfo 是发现内核模块泄漏的关键入口
当 ps 和 top 找不到高内存进程,但 free 的 available 持续掉,大概率是内核 slab 分配器里有泄漏——比如驱动、文件系统模块或自定义内核模块没释放 kmem_cache_alloc 的内存。
- 运行
slabtop -o(-o表示按使用量排序),重点关注OBJS和CACHE SIZE都异常大的条目,如ext4_inode_cache、tcp_bind_bucket、或你自己的模块名 -
cat /proc/slabinfo | awk '$2 > 10000 {print $1, $2}'快速筛出对象数超 1 万的 slab,再针对性查源码释放路径 - 注意区分
size-64、size-128这类通用缓存:它们增长未必是泄漏,但若长期不回收且与业务负载无关,就得怀疑底层分配未配对释放
valgrind 和 kmemleak 的适用边界必须分清
两者都是“检测工具”,但作用域完全隔离:一个管用户态,一个管内核态。混用或误选会导致白忙活。
-
valgrind --leak-check=full ./your_program只对单进程、非 daemon、非 setuid 程序有效;生产环境 Java/Go 进程要用jmap+ MAT 或go tool pprof,不是 valgrind -
kmemleak需要内核编译时开启CONFIG_DEBUG_KMEMLEAK,且默认关闭;启用后通过echo scan>/sys/kernel/debug/kmemleak触发扫描,输出中的unreferenced object地址需用echo dump=0x... > /sys/kernel/debug/kmemleak查堆栈 - 关键提醒:
kmemleak不会报告 slab 缓存本身的泄漏(如kmem_cache_create后没kmem_cache_destroy),它只报“分配后彻底丢失引用”的内存块——这类泄漏往往更隐蔽,得靠slabtop+ 模块代码审计双验证











