/proc/meminfo 是唯一准确反映内存去向的来源,free 的 used 列语义混乱;应重点关注 MemAvailable、AnonPages、Shmem、Active/Inactive(file)、Buffers 等字段,避免误判内存占用。

别信 free 的 used 行,直接看 /proc/meminfo
Linux 内存“被谁占了”这个问题,free 输出的 used 列根本不能回答。它在不同内核版本里语义不一致:free v3.2.8 是 total - free,v3.3.10 起变成 total - free - buff/cache,同一命令在两台机器上含义可能相反。
真正反映内存去向的,只有 /proc/meminfo 里的字段。它不是快照,而是内核实时维护的内存分类账本。运行:
cat /proc/meminfo
重点关注这些字段:
-
MemTotal:内核可支配的总物理内存(BIOS/固件/内核自身已扣减) -
MemAvailable:最该盯住的数字——内核估算的、可立即分配给新进程的内存,含可回收的 page cache、slab reclaimable 等 -
AnonPages:匿名页(堆、栈、mmap 匿名映射),不能被简单丢弃,OOM 前必须 swap 或 kill 进程 -
Shmem:tmpfs / shared memory 占用,计入Cached但属于“伪缓存”,实际是应用数据,不可回收 -
Active(file)和Inactive(file):分别表示最近/不常访问的文件缓存页,后者更易回收 -
Buffers:块设备 I/O 的底层缓冲(如 ext4 journal),现代内核中通常极小
MemAvailable 看起来够用,但系统还是 OOM?查 Shmem 和 Unevictable
MemAvailable 是启发式估算值,不是硬保证。它假设 Active(file)、Inactive(file)、SReclaimable 都能顺利回收,但以下情况会让它严重偏高:
-
Shmem占用大:比如/dev/shm下塞了几个 GB 的共享内存段,或容器挂载了大 tmpfs -
Unevictable内存存在:GPU 显存、mlock()锁定的内存、某些驱动分配的不可换出页
遇到 MemAvailable 还剩几百 MB 却频繁触发 OOM killer,立刻执行:
grep -i "shmem\|unevictable" /proc/meminfo
find /dev/shm /run -type f -size +1M 2>/dev/null | head -5
cat /proc/meminfo | grep -E "(AnonHugePages|HugePages_)"
区分 Cached 和 Buffers:一个管文件,一个管块设备
很多人把两者都叫“缓存”,但它们来源和行为完全不同:
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
-
Buffers:仅用于块设备 I/O 的元数据和临时缓冲(如磁盘扇区对齐、ext4 journal),现代内核中通常小于 10MB -
Cached:来自 VFS 层的 page cache,缓存的是文件内容本身;它包含Active(file)+Inactive(file)+ 部分Shmem,绝大部分可被回收(除非被mlock()或标记为Unevictable)
注意:Cached 不等于 cat /proc/meminfo | awk '/^Cached:/ {print $2}' 的原始值——因为 Shmem 被重复计入了 Cached 和 Shmem 字段,直接相加会重复统计。
想脚本化分析?优先解析 /proc/meminfo,别 parse free 输出
free 的输出格式随版本和参数变化剧烈(列数、单位、是否含 shared、available 是否存在),不适合写进监控脚本。而 /proc/meminfo 格式稳定、字段语义明确、无歧义。
例如,要获取当前可安全分配的内存(单位 KB):
awk '/^MemAvailable:/ {print $2}' /proc/meminfo要计算真正被进程“实打实”占用的内存(排除所有可回收项):
awk '/^MemTotal:/ {t=$2} /^MemFree:/ {f=$2} /^Buffers:/ {b=$2} /^Cached:/ {c=$2} /^SReclaimable:/ {s=$2} /^Shmem:/ {sh=$2} /^MemAvailable:/ {a=$2} END {print "AnonReal: " t-f-b-c+s+sh}' /proc/meminfo复杂点在于 Shmem 和 Unevictable 的干扰,它们让“可用”和“已用”的边界变得模糊——这恰恰是 Linux 内存管理的真实水位线,不是靠一个数字能概括的。

















