top显示内存占用异常:已用内存远超进程RES总和
嗨,我来给你拆解清楚——这是Linux内存统计里超常见的“坑”,你绝对不是第一个遇到的!
首先明确说:RES(Resident Memory)确实是进程实际驻留在物理内存中的内存占用量,这个指标本身是准确的,但它的总和不等于系统显示的“已用内存”,消失的10GB内存其实都藏在这些容易被忽略的地方:
共享内存的重复统计与遗漏
很多进程会共享系统核心库(比如libc.so),每个进程的RES都会把自己用到的共享内存部分算进去,但物理内存里其实只存了一份。反过来,像tmpfs挂载的文件系统、IPC共享内存段这类内核管理的共享内存,不会被计入任何进程的RES,但实实在在占用了物理内存。内核自身占用的内存
top默认只展示用户态进程的内存数据,内核使用的内存(比如内核代码、页表、slab分配器缓存、内核线程内存)都不在进程RES总和里。你可以用free -h查看buff/cache部分,或者用slabtop命令查看内核slab内存的占用情况,这部分往往占了不少空间。磁盘缓存与缓冲区
系统会把空闲物理内存自动用来做磁盘页缓存(page cache)和缓冲区,这部分在free的used统计里会被算进去,但不会被任何进程的RES计算。不过这不是“浪费”,是Linux的性能优化机制——当进程需要内存时,系统会自动回收这部分资源。隐藏的进程/内存结构
默认top不显示内核线程,你可以按H键切换显示线程看看;另外僵尸进程虽然不再运行,但可能残留一些内存结构,还有某些进程的匿名内存映射在特定情况下也可能没被top及时统计。
实操验证建议
你可以用这个命令计算所有进程RES的总和:
ps aux --sort=-%mem | awk '{sum+=$6} END {print sum/1024 " MB"}'
然后对比free -h的used值,差值基本就是上面提到的那些内存区域。另外推荐用smem工具(大部分发行版可通过包管理器安装),它会自动扣除共享内存的重复计算,给出更精准的“实际内存占用”统计,能帮你彻底理清内存去向。
内容的提问来源于stack exchange,提问作者user276483

