pmap是linux下查看进程内存映射的命令行工具,读取/proc/[pid]/maps输出进程各内存段(代码、堆、栈、共享库、匿名映射等)的地址、大小、rss、权限及映射来源等详情。

什么是 pmap,它能看什么
pmap 是 Linux 下一个轻量但精准的进程内存映射查看工具,它读取 /proc/[pid]/maps 并格式化输出,告诉你某个进程(比如 nginx 或你自己的 python3 脚本)到底加载了哪些内存段:可执行代码段、堆、栈、共享库、匿名映射、mmap 分配区等。它不采样、不估算,就是直接 dump 内核当前记录的映射快照。
注意:pmap 本身不分析内存泄漏,也不显示谁分配了某块内存——它只回答“这块地址现在映射了什么”,而不是“谁申请的”。想定位泄漏得配合 gdb、valgrind 或应用层 profiling。
怎么用 pmap 查看指定进程的完整映射详情
最常用的是加 -x(扩展模式)或 -XX(更详细,含 RSS/Dirty 等),再跟上进程 PID:
pmap -x 12345
其中 12345 是目标进程 PID。如果你只知道进程名,先用 pgrep 或 pidof 获取:
pgrep -f "python3 myapp.py"-
pidof nginx(注意可能返回多个 PID,选主 worker 或 master)
常见误区:
- 直接
pmap python3会报错——pmap必须接数字 PID,不接受进程名 - 对没有权限的进程(如其他用户启动的
systemd服务),会提示Permission denied;此时需sudo pmap -x [pid],但注意:sudo后看到的仍是该进程当时的映射,不是“提权后才有的”
pmap 输出各列含义和关键判断点
以 pmap -x [pid] 输出为例,典型列是:Address、Kbytes、RSS、Dirty、Mode、Mapping:
-
Address:起始虚拟地址(十六进制),可用于在gdb中检查某段内容 -
Kbytes:该段总大小(KB),包括未实际使用的页 -
RSS:常驻集大小(KB),即当前真正驻留在物理内存中的页数——比Kbytes小说明有部分被 swap 或尚未分配物理页 -
Dirty:被修改过、尚未写回磁盘的私有页(KB),值大可能意味着频繁写堆或 mmap 匿名区 -
Mode:权限标志,如rw-p(可读写、私有)、r-xp(可执行)、---p(无权限,可能是 guard page) -
Mapping:映射来源,空表示匿名映射(如堆、栈、mmap(MAP_ANONYMOUS)),否则是路径(如/lib/x86_64-linux-gnu/libc.so.6)
重点关注:anon 行(匿名映射)、[heap]、[stack] 和反复出现的大块 .so 库——它们往往是内存大户或加载异常的线索。
为什么有时 pmap 显示的 RSS 和 ps 不一致
ps aux --sort=-%mem 里的 %MEM 和 RES 列,底层也来自 /proc/[pid]/statm,但计算粒度与 pmap 不同:
-
ps RES是粗略的 RSS 总和,不含某些内核跟踪的细粒度页(如 page table 自身开销) -
pmap -x的RSS是逐段累加,更贴近/proc/[pid]/smaps的Rss:字段,精度更高 - 若发现
pmapRSS 比ps RES高出明显(比如 >10%),大概率是该进程用了大量mmap匿名映射(如 JVM 的 metaspace、Python 的mmap文件读取),而ps对这类映射统计不全
真要深挖差异,直接看 /proc/[pid]/smaps 更可靠,但可读性差;pmap 是平衡可读性与准确性的第一站。
别指望靠 pmap 一眼看出内存泄漏——它只告诉你“现在什么样”,不告诉你“为什么变成这样”。需要结合时间维度(多次 pmap -x 对比)、分配上下文(如是否调用了 mmap 或 brk)、以及应用逻辑才能归因。











