/proc/pid/maps是唯一能可靠区分代码段、数据段、bss、堆栈等内存映射的方法,因其按虚拟地址范围逐段列出权限标记(如r-xp为代码段、rw-p为数据段/堆/栈),而ps/top仅显示rss/vsz等聚合指标,无法识别段类型且高估独占内存。

直接看 /proc/pid/maps,再结合 pmap 或 readelf 对照验证 —— 这是唯一能可靠区分代码段(text)、数据段(data)、BSS、堆栈等实际内存映射的方法。
为什么不能只靠 ps 或 top 查代码段/数据段
ps 和 top 只显示聚合指标:RSS(驻留物理内存)、VSZ(虚拟内存大小),它们不区分段类型。一个进程的 RSS=100MB,可能是 5MB 代码段 + 95MB 堆,也可能是 80MB 数据段 + 20MB 栈 —— 完全无法判断。更关键的是,RSS 包含共享页(如 libc 的代码段被多个进程共用),直接归到单个进程头上会严重高估其“独占”代码段大小。
/proc/pid/maps 是最真实的一手视图
它按虚拟地址范围逐段列出内存映射,权限标记(r-xp / rw-p / rw-s)就是识别段类型的直接依据:
-
r-xp段:绝大多数是代码段(.text)、只读数据(.rodata)、共享库代码 —— 注意:不是所有r-xp都是你的主程序代码,得看Mapping列是否为可执行文件路径或[anon] -
rw-p段:通常是数据段(已初始化全局变量)、BSS(未初始化全局变量)、堆([heap])、栈([stack])—— 其中data和bss在进程启动时由内核从 ELF 文件加载,但运行中和堆混在一起,maps不显式标注哪块是 data/BSS,需结合readelf -S看原始节头偏移 -
rw-s段:共享内存(如 POSIX shm 或 System V shm),不属于传统代码/数据段范畴
示例命令:
cat /proc/1234/maps | grep -E 'r-xp|rwxp' | head -5
输出中类似 555555554000-555555575000 r-xp 00000000 08:01 1234567 /bin/bash 这一行,起始地址 555555554000 到结束地址 555555575000 就是 bash 主程序的代码段映射范围。
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
用 readelf -S 和 pmap -x 交叉验证段大小
ELF 文件里的节(section)信息是静态定义,/proc/pid/maps 是运行时实际映射,二者要对得上才说明没异常:
- 先查进程主可执行文件路径:
readlink /proc/1234/exe - 再看其代码段(
.text)和数据段(.data)的预期大小:readelf -S /path/to/binary | grep -E '\.(text|data|bss)'—— 注意Size列是字节数,不是内存页对齐后的实际映射长度 - 对比
pmap -x 1234输出中对应映射行的Kbytes列:比如.text节 Size 是 0x12345 字节,但pmap显示该r-xp映射占了 80KB,多出的部分是对其到页边界(通常 4KB)以及包含相邻只读节(如.rodata)导致的
关键点:ELF 的 .text 节大小 ≠ 进程 maps 中某 r-xp 行的大小,后者一定 ≥ 前者;而 .data 和 .bss 通常合并映射进同一个 rw-p 段,pmap 不拆分显示。
真正想读取代码段内容?必须用 ptrace + /proc/pid/mem
/proc/pid/mem 是只读虚拟文件,直接 cat 会报 Operation not permitted。绕过它的唯一合规方式是:
- 调用
ptrace(PTRACE_ATTACH, pid, NULL, NULL)绑定目标进程(需有 CAP_SYS_PTRACE 权限或同用户) - 绑定成功后,用
pread()从/proc/pid/mem读取指定地址 —— 地址必须落在/proc/pid/maps中标记为r-xp的范围内,否则返回EIO - 读完记得
ptrace(PTRACE_DETACH, pid, NULL, NULL),否则目标进程会被挂起
注意:ptrace 是侵入式操作,会暂停目标进程,生产环境慎用;且现代系统(如开启 YAMA)可能默认禁止非子进程 trace,需检查 /proc/sys/kernel/yama/ptrace_scope。
复杂点在于:代码段地址是虚拟地址,不同进程加载位置不同(ASLR 开启时),同一进程每次启动也不一样;数据段还涉及 copy-on-write 和动态链接器填充 —— 所以不要试图用固定地址去“硬读”,必须先解析 maps 动态获取范围。










