优先使用 /proc/pid/maps,因其是内核维护的一手实时映射快照,字段完整(地址、权限、偏移、inode、路径等),而pmap仅为封装解析器,易漏细节、受权限限制且统计不准确。

直接看 /proc/<pid>/maps</pid>,比 pmap 更原始、更全、更可靠。 它是内核暴露的实时映射快照,pmap 只是它的封装解析器,有时会漏掉细节或因权限问题报错。
为什么优先用 /proc/<pid>/maps</pid>
这个文件是内核维护的“一手数据”,每行代表一个虚拟内存区域,字段完整:起始地址、结束地址、权限、偏移、设备号、inode、映射路径(或 [anon]、[heap]、[stack] 等)。pmap 默认只显示大小和映射源,不展示偏移、inode 或完整地址范围。
- 权限列(如
r-xp)能快速识别可执行段(含潜在漏洞利用点) - 看到
[stack:12345]这种带 tid 的栈,说明是线程栈,不是主线程 - 遇到
---p权限的区域(如 libc 的 gap 段),pmap -x通常不计为“占用”,但它是真实存在的虚拟地址空洞 - 如果进程已退出但
/proc/<pid></pid>还没被清理(极短窗口),cat /proc/<pid>/maps</pid>会报No such process,而pmap可能静默失败或输出空
pmap 什么时候够用?怎么避免常见坑
日常排查 RSS/VSZ 占用、快速确认大块共享库加载情况时,pmap 更简洁。但要注意:
- 必须有目标进程的读权限;否则即使你是 root,若进程设置了
ptrace保护或YAMA限制,pmap会报Permission denied,而cat /proc/<pid>/maps</pid>同样失败 —— 不是工具问题,是内核策略 -
pmap -x输出的 “RSS” 是近似值,实际以/proc/<pid>/statm</pid>的第二列为准;pmap的 “Anon” 行不等于堆大小,它包含所有匿名映射(如 mmap(MAP_ANONYMOUS)、线程栈、brk 区域) - 别信
pmap最后一行的 “total”:它把所有映射大小简单相加,没去重,且包含未分配页(---p区域也算进去了),数值远大于实际物理内存占用
怎样快速定位关键内存区域
结合 grep 和 awk 直接过滤原始 maps:
- 查堆:
grep '\[heap\]' /proc/<pid>/maps</pid> - 查主线程栈:
grep '\[stack\]$' /proc/<pid>/maps</pid>(结尾无冒号) - 查所有私有可写区域(可能是堆或 malloc 缓存):
awk '$3 ~ /rw-p/ && $6 == "[anon]" {sum += $2} END {print sum}' /proc/<pid>/maps</pid>(单位 KB) - 查某个 so 是否被 mmap 多次:
grep 'libpthread\.so' /proc/<pid>/maps | wc -l</pid>(多次映射可能意味着 dlopen 动态加载)
真正难的不是找到地址空间,而是理解每一行背后的内存语义:比如 [vvar] 和 [vdso] 是内核优化的只读页,不计入 RSS;mmap(MAP_SHARED|MAP_HUGETLB) 映射的大页在 maps 里显示为普通区域,但实际物理页大小不同。这些细节,/proc/<pid>/maps</pid> 全都有,只是需要你懂它怎么说话。











