Linux 内存占用高一定是内存泄漏吗

13次阅读

内存占用高不等于内存泄漏,关键看 available 列是否充足;若 available≥总内存 10% 则多为缓存行为,需结合 ps 采样、valgrind 检测、OOM 日志及 slabtop 排查真泄漏。

Linux 内存占用高一定是内存泄漏吗

内存占用 高 ≠ 内存泄漏,先看 available 列再说话

绝大多数误判都发生在第一步:只盯着 free -h 输出里的 used 高就喊“内存爆了”。Linux 会把空闲内存自动用作 buff/cache(页缓存、目录项缓存等),这部分是可随时回收的,不构成压力。真正关键的是 available 列——它表示系统当前能立即分配给新进程、无需触发 swap 的内存预估量。如果 available 还剩总内存的 10% 以上(比如 16G 机器还有 2G+),那基本就是缓存行为,不是故障。

哪些情况会“假高”但不是泄漏

以下都是常见且合法的高内存占用场景,和程序 bug 无关:

  • slab_unreclaimable 占用突增:比如内核模块频繁创建 kmalloc-192 对象但未释放,属于内核态资源管理问题,不是用户进程泄漏
  • 共享内存段(/dev/shmipcs -m 查到的 shm)被长期持有:数据库、Redis、JVM 大页配置都可能显式申请并驻留大量共享内存
  • HugePages 被预分配:执行 cat /proc/meminfo | grep Huge,若 HugePages_Total 非零,这部分内存从启动起就被锁定,不参与常规回收
  • 内核 page cache 缓存大量文件:例如 rsync、tar 解压、日志轮转后未及时 drop_caches,buff/cache 可达数 GB,但 available 不变

怎么确认真是内存泄漏?盯住三件事

泄漏的本质是:进程 RES 内存持续缓慢上涨,且重启后回落,再运行又涨。验证需结合时间维度和进程视角:

  • ps aux --sort=-%mem | head -5 定期采样(如每 5 分钟一次),观察某个 PID 的 %MEMRSS 是否单向爬升
  • 检查该进程是否启用了 malloc 缓存(glibc 的 MALLOC_ARENA_MAX 默认值可能导致多线程程序内存“虚高”,设为 1 可缓解)
  • 对可疑二进制(如自研服务),在测试环境用 valgrind --leak-check=full ./your_app 检测,但注意:生产环境禁用,它会拖慢 10 倍以上且吃额外内存
  • Java 应用别只看 top 的 RES:JVM 堆外内存(Netty direct buffer、JNI)也可能泄漏,得用 jcmd VM.native_memory summary

容易被忽略的“真凶”:OOM Killer 日志和 slabtop

available 真的见底,系统不是静默崩溃,而是会启动 OOM Killer 杀进程保命。此时最直接证据是:

  • dmesg | grep -i "killed process" —— 若输出类似 Killed process 12345 (python) total-vm:8452345kB, anon-rss:7654321kB,说明已触发保护机制
  • slabtop -s c(按缓存对象数排序)—— 如果 kmalloc-xxxext4_inode_cacheOBJ/SLAB 列远高于常态,且 /sys/kernel/slab//reclaim_account 返回 0,大概率是内核 slab 泄漏,和用户代码无关

查到这里还找不到源头?说明问题不在应用层,而在内核模块、驱动或容器运行时(如 containerd 的 shim 进程异常)。这时候 crash 工具 配合 vmlinux 调试符号才是正解,而不是继续翻 top

text=ZqhQzanResources