pmap本身不生成分布图,仅输出内核VMA快照文本;执行pmap -x [pid]可获取地址、大小、权限及映射来源等原始数据,是构建内存分布视图的基础依据。

pmap 本身不生成“分布图”,它输出的是内核维护的 VMA(Virtual Memory Area)快照,本质是文本表格——所谓“图”得靠人解读或后续可视化。直接跑 pmap -x [pid] 就能拿到全部映射段的地址、大小、权限和来源,这是最接近“分布图”的原始依据。
怎么快速定位中间件进程 PID 并确认权限可读
中间件如 nginx、redis-server、java 进程常以非 root 用户启动,但主进程可能由 systemd 管理,导致普通用户查不到其 /proc/[pid]/maps:
- 先用
pgrep -f "nginx|redis|java.*myapp"或systemctl show --property MainPID nginx拿到真实 PID - 运行
ls -l /proc/[pid]/maps:若返回Permission denied,不是 sudo 权限不够,而是该进程设置了PR_SET_DUMPABLE=0(常见于加固后的 Java 应用或容器中),此时sudo pmap -x [pid]也无效 - 对容器内进程,需进入对应 namespace 查看:
nsenter -t [pid] -m -p sh -c 'cat /proc/1/maps',再喂给pmap格式化(需手动处理)
pmap -x 输出里哪些行对应中间件核心内存段
中间件内存大户通常集中在匿名映射和共享库,别被 [heap] 和 [stack] 带偏:
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
-
[anon]行(Mapping 列为空):大概率是mmap(MAP_ANONYMOUS)分配的大块缓存,比如 Redis 的maxmemory预分配、Nginx 的proxy_buffer区域——看Kbytes和RSS是否持续增长 -
[heap]行:仅表示 brk 区域起点,实际 malloc 小块内存不会新增 VMA,所以它大小不变 ≠ 没内存泄漏;真正堆膨胀会体现为某段[anon]显著变大 - 反复出现的
.so库(如libjemalloc.so、libz.so):若其RSS异常高,说明该库内部管理的内存(如 jemalloc 的 arena)驻留物理页多,需结合malloc_stats()或LD_PRELOAD跟踪 -
[vdso]、[vvar]、[vectors]这些内核提供段:固定大小(几 KB),忽略即可
为什么不能用 pmap 定位具体对象或泄漏点
pmap 是内核视角工具,它只告诉你“地址 A–B 映射了什么”,不回答“谁在地址 A 分配了 64 字节”:
-
malloc(64)不触发 mmap,只是从已有[heap]或[anon]段里切分,这些切分点不生成新 VMA,pmap看不见 - Java 应用的堆(
java -Xmx2g)在pmap中表现为一大段[anon],但无法区分 Eden/Survivor/Old 区——JVM 自己管理,内核只管页映射 - 若看到某
[anon]段 RSS 持续上涨,得配合gdb -p [pid]+info proc mappings看原始/proc/[pid]/maps,再用cat /proc/[pid]/smaps_rollup看总AnonPages和Shmem,排除 tmpfs 或共享内存干扰
真正难的不是跑出 pmap 输出,而是把 Address/Kbytes/RSS 这些数字和中间件配置、代码行为、内核页状态串起来——比如 Nginx 的 worker_connections × buffer_size 理论上限,是否和某段 [anon] 大小吻合;又比如 Redis 的 maxmemory 设置为 4G,但 pmap 显示 [anon] 占了 6G,那多半是 overcommit_memory=1 下的虚假分配,还没真正驻留物理页。










