ps的%mem不靠谱,因按rss统计且重复计算共享内存;uss反映独占内存,pss按进程数均摊共享页更合理;pmap -x看shared估算共享量,/proc/pid/smaps可精确获取pss和uss。

Linux里ps显示的%MEM到底靠不靠谱?
ps aux里的%MEM列实际是按RSS(常驻集大小)算的,但RSS会把共享内存(比如libc、glibc映射)全算进每个进程头上——多个进程共用同一段物理内存,却各自被记了一次。结果就是:所有进程RSS加起来远超物理内存总量,看着像“内存泄露”,其实只是重复统计。
真正反映单个进程独占物理内存的是USS(Unique Set Size),而PSS(Proportional Set Size)更合理:它把共享页按进程数均摊,比如一段4MB的libc被5个进程共享,每个进程的PSS只加0.8MB。
所以别只盯着ps——它看不到USS和PSS,也分不清哪些是共享、哪些是私有。
用pmap -x看单个进程的内存分布细节
pmap -x <pid></pid>能列出进程所有内存段的Size、RSS、Dirty,最后一行的mapped和shared字段特别关键:
-
mapped≈VSS(Virtual Set Size),即进程地址空间总大小,含未分配、未访问的页,参考价值低 -
shared是当前被其他进程共享的物理内存页(单位KB),值越大说明该进程越“轻量”(依赖共享库多) -
private(没直接显示,但可用mapped - shared粗略估算)接近USS上限,但不精确——因为有些“私有”页可能还没写入物理内存
示例:pmap -x 1234 | tail -1 输出:total 123456 78901 12345 → VSS=123456KB,RSS=78901KB,shared=12345KB。
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
用/proc/<pid>/smaps</pid>算准PSS和USS
/proc/<pid>/smaps</pid>是Linux内核提供的最权威内存明细,每块内存区域都有独立的Pss(注意大小写)、Uss、Rss字段。要得到整个进程的汇总值,得自己加总:
-
grep -i 'pss\|uss' /proc/1234/smaps | awk '{sum += $2} END {print sum}'→ 得到总PSS(KB) -
awk '/^Uss:/ {sum += $2} END {print sum+0}' /proc/1234/smaps→ 更稳,+0防空输出
注意:Uss在旧内核(/proc/sys/vm/oom_dump_tasks为1且内核编译时打开了CONFIG_MEMCG_KMEM;否则Uss:行不存在,只能用Pss替代评估独占性。
批量查PSS/USS推荐用smem工具,别手写脚本
手动解析smaps太慢,尤其进程多时。直接装smem(Debian/Ubuntu:apt install smem;RHEL/CentOS:yum install python3-smem):
-
smem -c "pid comm pss uss" -s uss→ 按USS排序,找真正吃内存的“大户” -
smem --pie=name -s pss→ 生成饼图,一眼看出谁占了共享内存大头 -
smem -P nginx -k→ 查所有nginx进程的PSS(KB)和USS(KB),带单位
smem底层就是读smaps,但它自动处理了权限、空值、内核版本兼容等问题,比自己grep+awk可靠得多。唯一要注意:非root用户可能看不到其他用户的smaps,报Permission denied——这时候要么切root,要么只查自己启动的进程。
复杂点在于USS不是永远可得,而PSS虽稳定但仍是估算(共享页按进程数平分,实际使用频率不同)。真要定位内存泄漏,得结合valgrind或perf mem看具体分配点,光看smaps只能划范围。










