pmap 拆解内存构成
pmap 来自 procps-ng,读取进程的内存映射表(即 /proc/PID/maps 与 smaps),列出一段段内存的地址范围、大小、实际驻留情况以及这段映射从哪来。当 top 只告诉你 RES 数字、却看不出内存去哪时,pmap 能直接把大头指出来:是堆在涨、是共享库占多、还是线程栈堆积。
基本信息
| 适用平台 | Linux(procps-ng 包) |
|---|---|
| 语法 | pmap [-x | -X | -d] PID [PID...] |
| 权限要求 | 查看自有进程即可;查看他人进程需 root |
| 数据来源 | /proc/PID/maps 与 /proc/PID/smaps |
典型使用场景
- 排查「内存去哪了」:定位占 RSS 最大的映射段
- 确认共享库被多少个进程共用、总量是否被重复计算
- 观察堆、栈、匿名映射构成,判断是泄漏还是正常缓存
- 对比崩溃前后的内存映射差异
- 给容器或服务设置内存上限前先摸清实际占用构成
常用示例
常用示例
pmap -x 1234 | tail -5 # 末尾几行是总计
pmap -X 1234 | sort -k3 -rn | head -10 # 按 RSS 排序,找最大映射段
pmap -x 1234 | grep -E 'heap|stack|\[anon\]' # 只看堆、栈与匿名段
pmap 1234 | grep '\.so' | head # 共享库映射
cat /proc/1234/smaps_rollup # 一行摘要:总量与 PSS,更适合脚本
wc -l < /proc/1234/maps # 映射段数量,异常多时配合排查输出逐列读法
| 列 | 含义 | 关注点 |
|---|---|---|
| Address | 该段内存的起止地址 | 连续大段通常对应大块分配 |
| Kbytes | 映射的虚拟大小 | 虚拟大小不等于实际占用,别据此判断内存不足 |
| RSS | 实际驻留物理内存 | 排内存问题的核心列 |
| Dirty | 私有的已修改页 | 持续上升通常意味着进程内存真实增长 |
| Mapping | 映射来源:文件名、[heap]、[stack]、[anon] | [anon] 多说明是程序自己申请的内存 |
把所有进程的 RSS 简单相加会远超物理内存,因为共享库被多进程共用。要做去重统计用 PSS(/proc/PID/smaps_rollup 或 smaps 里的 Pss 字段)更准确。
pmap 只能看当前活着的进程。要看历史趋势必须靠监控采样,事后对已退出的进程没有数据可取。
排查套路
- 先看末尾的总计行确认整体占用,再按驻留大小排序找出占用最大的映射段
- 间隔一段时间采样两次做对比,判断是启动后稳定还是持续攀升
- 重点关注堆与匿名映射段,程序自身申请的内存通常体现在这里
- 共享库段偏大属于正常现象,被多进程共用的部分不应算作该进程独占
- 结合应用自身的统计接口或分配日志交叉验证,避免只看单一视角
内存占用上升不等于泄漏:缓存增长、连接池预热都会抬高数值,判断泄漏要看长期斜率以及是否出现只增不减的形态。