
Linux内存持续上涨,首先要区分是“缓存增长”还是“真实泄漏”。系统会自动利用空闲内存做页缓存(buff/cache),这是正常且有益的行为;但若 available 持续下降、buff/cache 单向上涨不回落、Slab 长期攀升,就极可能是内存泄漏——必须立即排查。
看 free:盯住 available 和 buff/cache 的变化趋势
运行 watch -n 5 'free -h' 每5秒刷新一次,重点关注:
- available:不是 free 列,而是内核估算的“此刻能立刻分配给新进程”的内存。它持续走低(尤其从几G掉到几百M)是泄漏强信号;
- buff/cache:包含 page cache、dentry/inode、slab 对象等。短期上涨合理,但若随时间单向增长、且 available 不同步回升,说明有内存被“钉住”无法回收;
- 别迷信 used:used = total − free − buff/cache,而 buff/cache 中大部分可随时释放,所以 used 上涨 ≠ 泄漏。
查 vmstat:确认系统是否在“挣扎”
执行 vmstat 1 观察每秒状态,关键字段:
- sr(或 re)> 0 且持续存在:kswapd 内核线程正疯狂扫描 LRU 链表回收内存,表明内存压力已实质化;
- si/so 非零并跳动:开始 swap 换页,物理内存严重不足;
- in(中断)和 cs(上下文切换)异常升高 + 内存下降:可能指向高频内核分配路径,比如网络收包、定时器回调反复申请内存。
定位泄漏源头:分用户态和内核态两路追
确认异常后,快速缩小范围:
-
用户进程侧:用
ps aux --sort=-%mem | head -10查 RSS 最高进程,结合其生命周期判断——是否本该退出却常驻?连接数/请求数是否线性增长?再用pmap -x <pid></pid>看堆、mmap 区是否持续扩张; -
内核侧重点看 Slab:执行
cat /proc/meminfo | grep -E "Slab|SReclaimable|SUnreclaim"。若 Slab 持续涨、SReclaimable 不涨(即不可回收部分占比高),大概率是驱动或内核模块中 kmalloc 分配后未 kfree; - 进一步用
slabtop找增长最快的 slab cache(如 dentry、size-4096),再结合/proc/slabinfo确认对象数量变化; - 确认是内核泄漏后,可用
trace-cmd record -e kmem:kmalloc -e kmem:kfree -T跟踪特定大小分配/释放,比对 ptr 地址是否成对出现。
常见诱因与速查建议
很多“内存上涨”其实有明确归因,可优先验证:
- curl HTTPS 探测脚本:旧版 curl(如 7.19.7)+ NSS 库存在 dentry 泄漏,停掉探测脚本或升级 curl 即可缓解;
- /proc/schedstat 读取:某些内核版本中反复读该文件会泄漏 size-4096 内存,上游已有补丁(commit 8e0bcc722289);
- BPF 程序或 eBPF map:未设置 max_entries 或未及时清理过期条目,导致内核内存持续累积;
- tmpfs 大文件残留:如 /dev/shm 下未清理的共享内存文件,直接占用物理内存且不计入 buff/cache。










