排查共享内存泄漏需先用pmap -x识别可写且共享(Mode含w和s)的映射,重点关注RSS持续增长、重复映射或匿名共享段未释放;再通过/proc/PID/smaps核验Shared_Clean/Dirty与Private_Dirty,确认是否发生写时复制导致实质私有化。

排查共享内存段泄漏,关键不是看“共享”本身,而是识别本该被多个进程共用、却因逻辑错误变成私有占用或未释放的内存区域。pmap -x 不能直接标记“共享内存泄漏”,但它能暴露异常行为:比如某块标为 s(shared)的映射 RSS 持续增长,或本应共享的区域在进程中反复重复映射。
重点看 Mapping 和 Mode 列的组合信号
pmap -x 输出中,真正代表传统 IPC 共享内存(如 shm_open/mmap 或 System V shm)的行,Mapping 列通常显示为 /dev/zero、[shmid=xxx] 或具体路径(如 /tmp/myshm),Mode 列含 s(shared)。但要注意:
- 很多“共享库”(如 libc.so)也带 s 标志,但它们是只读代码段,不会泄漏——关注的是 可写 + 共享 的区域,即 Mode 同时含 w 和 s
- 如果看到多个地址段 Mapping 都指向同一个文件(如 /tmp/shm_data)但各自 RSS 独立增长,说明各进程没复用同一块物理页,可能是创建时没设 MAP_SHARED,或使用了私有映射替代共享
- Mapping 显示 [anon] 且 Mode 含 s,通常是 POSIX 共享内存或大页映射,这类匿名共享段若 RSS 不降,需检查是否所有关联进程都已正常 detach 和 unlink
用 RSS 增长趋势锁定可疑共享段
共享内存泄漏的典型表现不是单次分配大,而是随时间推移,某块共享映射的 RSS 持续上升,且不随其他进程退出而回落:
- 执行 pmap -x PID 记录初始值,间隔 30 秒再执行一次,用工具或手动对比相同 Mapping 行的 RSS 列
- 特别注意那些 Kbytes 很大但初始 RSS 很小、随后 RSS 快速逼近 Kbytes 的共享段——说明数据正不断写入,但无人清理或释放
- 若发现多个不同 PID 对应同一共享文件(如 /dev/shm/mycache)的 RSS 总和远超预期容量,说明存在重复映射或未 unmap
结合 /proc/PID/smaps 验证共享性真实性
pmap -x 的 Mode 字段只是权限标识,不能反映实际物理页共享状态。要确认是否真共享,必须查 smaps:
- 找到可疑 Mapping 行的 Address 起始地址(如 00007f8b2c000000)
- 运行 grep -A 5 -B 5 "00007f8b2c000000" /proc/PID/smaps
- 查看 Shared_Clean、Shared_Dirty、Private_Dirty 三列:若 Shared_* 高而 Private_Dirty 也高,说明该进程在修改共享页的同时触发了写时复制(COW),实质已变成私有占用——这就是泄漏根源之一
区分泄漏与正常缓存增长
某些共享内存设计本就是缓存用途(如 Redis 的共享字典、数据库的共享缓冲池),RSS 上升未必是 bug:
- 检查应用是否有明确的缓存淘汰策略(LRU/LFU),并观察其是否生效
- 对比 Shared_Clean 和 Shared_Dirty:长期 Dirty 高,说明数据持续更新但无回收机制;Clean 高且稳定,更可能是合理缓存
- 若共享段 Mapping 显示为 [heap] 或 [stack] 却带 s 标志,属于异常,应立即检查代码是否误用 mmap(MAP_SHARED) 分配堆内存
不复杂但容易忽略:共享内存泄漏往往藏在“大家都以为别人会清理”的逻辑里。pmap -x 是第一面镜子,照出谁在涨;smaps 才是显微镜,看清涨的是谁的页。


















