linux内存持续增长需先排除缓存,再分用户态(ps/pmap/asan/jstat)和内核态(slabtop/perf/bpftrace)排查;关注memavailable、slab、rss等指标变化,结合cgroup、oom日志等辅助定位。

Linux 系统中内存持续增长,不一定是内存泄漏,但一旦排除缓存、缓冲区等正常占用后仍持续上涨,就需深入排查。关键在于区分 内核态内存增长 和 用户态进程内存泄漏,二者定位手段差异较大。
确认是否真为内存泄漏
先用基础命令观察内存使用趋势,避免误判:
-
free -h 查看整体内存(重点关注
available是否持续下降,而非used;Linux 会积极使用空闲内存作 page cache,这属于正常行为) -
cat /proc/meminfo 检查
MemAvailable、Slab、PageTables、KernelStack等字段变化,若Slab持续上涨,可能指向内核对象泄漏 - watch -n 1 'ps aux --sort=-%mem | head -10' 观察用户进程 RSS 是否随时间单调上升(注意排除刚启动、正在加载数据的进程)
定位用户态进程内存泄漏
聚焦单个可疑进程,结合运行时与堆分析:
-
pmap -x
查看进程各内存段大小,关注 anon映射和堆([heap])是否持续扩大 -
/proc/
/smaps 中搜索Size:和RSS:,按mmapped或heap区域筛选,用awk统计总和并定时采样对比 - 对 C/C++ 程序,启用 AddressSanitizer(ASan) 重新编译运行:
gcc -fsanitize=address -g test.c,可捕获堆内存越界、重复释放、泄漏等;运行后 ASan 会在退出时打印未释放内存摘要 - Java 应用用 jstat -gc
观察老年代使用量是否持续增长且 Full GC 后不回落,再配合 jmap -histo:live 或 jcmd VM.native_memory summary 辅助判断
排查内核态内存异常增长
当 Slab、PageTables、PerCPU 等内核内存项持续上涨,需深入内核视角:
-
slabtop 实时查看 slab 缓存使用,重点关注
#objs和ObjSize都大的缓存项(如dentry、inode_cache、ext4_inode_cache),结合ls -R /path是否触发大量目录遍历可辅助验证 -
cat /sys/kernel/slab/*/alloc_calls 可定位高频分配的 slab 类型;
grep -r "alloc" /sys/kernel/debug/slab/(需开启slab_debug)进一步分析 - 使用 perf 抓取内核内存分配栈:
perf record -e kmem:kmalloc,kmem:kfree -a sleep 30,再用perf script查看高频分配点;对较新内核可尝试memleakbpftrace 工具:sudo bpftrace -e 'kprobe:kmalloc { @bytes = hist(arg2); } interval:s:10 { print(@bytes); clear(@bytes); }' - 检查是否有异常模块加载或驱动 bug:用
lsmod查最近加载模块,dmesg -T | grep -i "out of memory\|slab\|memory"搜索内核日志线索
辅助手段与注意事项
提升排查效率的实用技巧:
- 用 systemd-cgtop 或
cat /sys/fs/cgroup/memory/.../memory.usage_in_bytes查看 cgroup 级别内存走势,确认是否某服务组整体失控 - 对长期运行服务,设置 memory limit + OOMKill(如 systemd 的
MemoryMax=),配合日志观察是否被 kill,可反向锁定泄漏节奏 - 避免在生产环境直接启用
slab_debug或KASAN,它们有显著性能开销;优先在复现环境测试 - 注意 mmap(MAP_ANONYMOUS) 分配的大块内存不会计入进程 RSS,但算入
VirtualSize,需用pmap或smaps中MMUPageSize相关字段识别








