上篇介绍了QNX中使用pidin mem来分析进程的内存,本篇继续了讨论另一个pmap文件来分析进程的内存使用。
1 获取数据
在此次分析pmap时,会和上篇分析的pidin mem的数据做对比。因为每次开机,进程的ID可能是随机,需要再获取一次pidin mem的数据。
pidin
可以用pidin指令查看当次开机的所有进程的ID:
# pidin
pid tid name prio STATE Blocked
1 1 /proc/boot/procnto-smp-instr 0f READY
1 2 /proc/boot/procnto-smp-instr 0f READY
1 3 /proc/boot/procnto-smp-instr 255i INTR
1 4 /proc/boot/procnto-smp-instr 255i INTR
1 5 /proc/boot/procnto-smp-instr 254i INTR
1 6 /proc/boot/procnto-smp-instr 254i INTR
1 7 /proc/boot/procnto-smp-instr 1f NANOSLEEP
1 8 /proc/boot/procnto-smp-instr 10r ???
1 9 /proc/boot/procnto-smp-instr 10r RECEIVE 1
1 10 /proc/boot/procnto-smp-instr 10r RECEIVE 1
1 11 /proc/boot/procnto-smp-instr 11r RECEIVE 1
1 12 /proc/boot/procnto-smp-instr 10r RECEIVE 1
1 13 /proc/boot/procnto-smp-instr 10r RECEIVE 1
1 14 /proc/boot/procnto-smp-instr 10r RUNNING
1 15 /proc/boot/procnto-smp-instr 10r RECEIVE 1
1 16 /proc/boot/procnto-smp-instr 10r RECEIVE 1
16387 1 proc/boot/slogger2 10r RECEIVE 1
28676 1 proc/boot/pci-server 10r RECEIVE 1
28676 2 proc/boot/pci-server 10r RECEIVE 1
28676 3 proc/boot/pci-server 21r RECEIVE 1
28676 4 proc/boot/pci-server 10r RECEIVE 1
49157 1 proc/boot/fsevmgr 10r SIGWAITINFO
49157 2 proc/boot/fsevmgr 10r RECEIVE 1
49157 3 proc/boot/fsevmgr 10r RECEIVE 2
49157 4 proc/boot/fsevmgr 10r RECEIVE 1
53254 1 proc/boot/devb-eide 10r SIGWAITINFO
53254 2 proc/boot/devb-eide 21r RECEIVE 1
53254 3 proc/boot/devb-eide 254i INTR
53254 4 proc/boot/devb-eide 21r RECEIVE 3
53254 5 proc/boot/devb-eide 10r RECEIVE 4
53254 6 proc/boot/devb-eide 10r RECEIVE 5
#省略...
#
pidin -p <pid> mem
比如我们来用proc/boot/slogger2分析,它的PID是16387,可以使用指令pidin -p 16387 mem来打印出单个进程的信息:
# pidin -p 16387 mem
pid tid name prio STATE code data stack
16387 1 proc/boot/slogger2 10r RECEIVE 1108K 476K 512K/512K
slogger2 @367cce0000 64K 8192
ldqnx-64.so.2 @2806fb3000 224K 12K
libslog2.so.1 @2806fef000 20K 4096
libsecpol.so.1 @2806ff6000 20K 4096
libc.so.6 @2806ffd000 668K 8192
libgcc_s.so.1 @28070b0000 112K 4096
/shmem/slogger2/console.16387 @1af522e000 ( 0) 20K
hmem/slogger2/devb_eide.53254 @1af5233000 ( 0) 68K
/shmem/slogger2/io_hid.118791 @1af5244000 ( 0) 68K
hmem/slogger2/devc_pty.200719 @1af5255000 ( 0) 68K
/shmem/slogger2/dhcpcd.266259 @1af5266000 ( 0) 68K
**zero ELF** @2806fee000 ( 0) 4096
**zero ELF** @2806ff4000 ( 0) 4096
**zero ELF** @2806ffb000 ( 0) 4096
**zero ELF** @28070a4000 ( 0) 16K
**zero ELF** @28070aa000 ( 0) 24K
**zero ELF** @28070cc000 ( 0) 4096
**zero ELF** @367ccf2000 ( 0) 4096
**heap** @5ddfc4c000 ( 0) 84K
#
cat /proc/<pid>/pmap
pmap的信息,是在文件中的,可以用指令cat /proc/16387/pmap来查看16387进程的信息
详细数据如下,手动去掉了一些前导0:
| vaddr | size | flags | prot | maxprot | dev | ino | offset | rsv | guardsize | refcnt | mapcnt | path | asinfo |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0x1af522e000 | 0x05000 | 0x20001 | 0x03 | 0x0f | 0x001 | 0xd251d8adec41f5c0 | 0x00000 | 0x00000 | 0x0000 | 0x003 | 0x001 | /dev/shmem/slogger2/console.16387 | {sysram} |
| 0x1af5233000 | 0x11000 | 0x00001 | 0x03 | 0x0f | 0x001 | 0xd251d8adec41cb60 | 0x00000 | 0x00000 | 0x0000 | 0x003 | 0x001 | /dev/shmem/slogger2/devb_eide.53254 | {sysram} |
| 0x1af5244000 | 0x11000 | 0x00001 | 0x03 | 0x0f | 0x001 | 0xd251d8adec41d090 | 0x00000 | 0x00000 | 0x0000 | 0x003 | 0x001 | /dev/shmem/slogger2/io_hid.118791 | {sysram} |
| 0x1af5255000 | 0x11000 | 0x00001 | 0x03 | 0x0f | 0x001 | 0xd251d8adec41a6f0 | 0x00000 | 0x00000 | 0x0000 | 0x003 | 0x001 | /dev/shmem/slogger2/devc_pty.200719 | {sysram} |
| 0x1af5266000 | 0x11000 | 0x00001 | 0x03 | 0x0f | 0x001 | 0xd251d8adec419850 | 0x00000 | 0x00000 | 0x0000 | 0x003 | 0x001 | /dev/shmem/slogger2/dhcpcd.266259 | {sysram} |
| 0x2806fb3000 | 0x38000 | 0x10031 | 0x05 | 0x0d | 0x802 | 0x000000008000003e | 0x00000 | 0x00000 | 0x0000 | 0x15b | 0x159 | /proc/boot/ldqnx-64.so.2 | {ram} |
| 0x2806feb000 | 0x02000 | 0x10032 | 0x01 | 0x0f | 0x802 | 0x000000008000003e | 0x37000 | 0x02000 | 0x0000 | 0x15b | 0x159 | /proc/boot/ldqnx-64.so.2 | {ram} |
| 0x2806fed000 | 0x01000 | 0x10032 | 0x03 | 0x0f | 0x802 | 0x000000008000003e | 0x39000 | 0x01000 | 0x0000 | 0x15b | 0x159 | /proc/boot/ldqnx-64.so.2 | {ram} |
| 0x2806fee000 | 0x01000 | 0x80032 | 0x03 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x01000 | 0x0000 | 0x000 | 0x162 | {bss} | {sysram} |
| 0x2806fef000 | 0x05000 | 0x10031 | 0x05 | 0x0d | 0x802 | 0x0000000080000046 | 0x00000 | 0x00000 | 0x0000 | 0x15b | 0x159 | /proc/boot/libslog2.so.1 | {ram} |
| 0x2806ff4000 | 0x01000 | 0x80032 | 0x01 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x01000 | 0x0000 | 0x000 | 0x162 | {bss} | {sysram} |
| 0x2806ff5000 | 0x01000 | 0x10032 | 0x03 | 0x0f | 0x802 | 0x0000000080000046 | 0x05000 | 0x01000 | 0x0000 | 0x15b | 0x159 | /proc/boot/libslog2.so.1 | {ram} |
| 0x2806ff6000 | 0x05000 | 0x10031 | 0x05 | 0x0d | 0x802 | 0x000000008000004d | 0x00000 | 0x00000 | 0x0000 | 0x15b | 0x159 | /proc/boot/libsecpol.so.1 | {ram} |
| 0x2806ffb000 | 0x01000 | 0x80032 | 0x01 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x01000 | 0x0000 | 0x000 | 0x162 | {bss} | {sysram} |
| 0x2806ffc000 | 0x01000 | 0x10032 | 0x03 | 0x0f | 0x802 | 0x000000008000004d | 0x05000 | 0x01000 | 0x0000 | 0x15b | 0x159 | /proc/boot/libsecpol.so.1 | {ram} |
| 0x2806ffd000 | 0xa7000 | 0x10031 | 0x05 | 0x0d | 0x802 | 0x000000008000003d | 0x00000 | 0x00000 | 0x0000 | 0x15b | 0x159 | /proc/boot/libc.so.6 | {ram} |
| 0x28070a4000 | 0x04000 | 0x80032 | 0x01 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x04000 | 0x0000 | 0x000 | 0x162 | {bss} | {sysram} |
| 0x28070a8000 | 0x02000 | 0x10032 | 0x03 | 0x0f | 0x802 | 0x000000008000003d | 0xaa000 | 0x02000 | 0x0000 | 0x15b | 0x159 | /proc/boot/libc.so.6 | {ram} |
| 0x28070aa000 | 0x06000 | 0x80032 | 0x03 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x06000 | 0x0000 | 0x000 | 0x162 | {bss} | {sysram} |
| 0x28070b0000 | 0x1c000 | 0x10031 | 0x05 | 0x0d | 0x802 | 0x000000008000003f | 0x00000 | 0x00000 | 0x0000 | 0x15b | 0x159 | /proc/boot/libgcc_s.so.1 | {ram} |
| 0x28070cc000 | 0x01000 | 0x80032 | 0x01 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x01000 | 0x0000 | 0x000 | 0x162 | {bss} | {sysram} |
| 0x28070cd000 | 0x01000 | 0x10032 | 0x03 | 0x0f | 0x802 | 0x000000008000003f | 0x1d000 | 0x01000 | 0x0000 | 0x15b | 0x159 | /proc/boot/libgcc_s.so.1 | {ram} |
| 0x367cce0000 | 0x10000 | 0x10031 | 0x05 | 0x0d | 0x802 | 0x000000008000001f | 0x00000 | 0x00000 | 0x0000 | 0x15b | 0x159 | /proc/boot/slogger2 | {ram} |
| 0x367ccf0000 | 0x01000 | 0x10032 | 0x01 | 0x0f | 0x802 | 0x000000008000001f | 0x0f000 | 0x01000 | 0x0000 | 0x15b | 0x159 | /proc/boot/slogger2 | {ram} |
| 0x367ccf1000 | 0x01000 | 0x10032 | 0x03 | 0x0f | 0x802 | 0x000000008000001f | 0x10000 | 0x01000 | 0x0000 | 0x15b | 0x159 | /proc/boot/slogger2 | {ram} |
| 0x367ccf2000 | 0x01000 | 0x80032 | 0x03 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x01000 | 0x0000 | 0x000 | 0x162 | {bss} | {sysram} |
| 0x403aeab000 | 0x80000 | 0x81002 | 0x03 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x80000 | 0x1000 | 0x000 | 0x162 | {stack} | {sysram} |
| 0x5ddfc4c000 | 0x15000 | 0x80002 | 0x03 | 0x0f | 0x001 | 0x0000000000000003 | 0x00000 | 0x15000 | 0x0000 | 0x000 | 0x162 | {heap} | {sysram} |
2 pmap字段含义
截取表头和第一行数据如下
vaddr,size,flags,prot,maxprot,dev,ino,offset,rsv,guardsize,refcnt,mapcnt,path,asinfo
0x0000001af522e000,0x0000000000005000,0x00020001,0x03,0x0f,0x00000001,0xd251d8adec41f5c0,0x0000000000000000,0x0000000000000000,0x00000000,0x00000003,0x00000001,/dev/shmem/slogger2/console.16387,{sysram}
表头含义
| 字段 | 含义 | 举例 |
|---|---|---|
vaddr |
虚拟地址起始 | 0x0000001af522e000 |
size |
区域长度(字节,十六进制) | 0x0000000000005000 |
flags |
mmap 标志位 | 0x00020001 |
prot |
当前保护位,PROT_* 右移 8 位 | 0x03 |
maxprot |
prot 能取到的最大值,同样右移 8 位 | 0x0f |
dev |
对象所在设备 ID(0x802=IFS,0x1=匿名/shmem) |
0x00000001 |
ino |
对象 inode(文件对象各异;匿名对象恒为 3) | 0xd251d8adec41f5c0 |
offset |
在对象内的起始偏移(code/bss=0;data=文件内偏移) | 0x0000000000000000 |
rsv |
该区域为这个进程预留的物理内存 | 0x0000000000000000 |
guardsize |
保护页大小(只有 stack 有 0x1000) |
0x00000000 |
refcnt |
对象的引用数 | 0x00000003 |
mapcnt |
唯一映射数 | 0x00000001 |
path |
后端对象名 | /dev/shmem/slogger2/console.16387 |
asinfo |
供页的地址空间段 | {sysram} |
具体介绍表头中某些数据的含义
2.1 flags
按位掩码
这次 28 行实际用到的位有 7 个:bit 19(ANON)、17(NOX64K)、16(PHYS)、12(STACK)、5(ELF)、4(FIXED)、1–0(类型)。
- 0x00000001 SHARED0x00000002 PRIVATE0x00000020 ELF 相关(code/data/bss 都有)0x00000010 FIXED0x00001000 STACK0x00010000 有文件内容的 ELF 段(code/data)0x00020000 NOK64K0x00080000 ANON
完整的定义如下表
| bit | 值 | 名称 | 含义 | 类别 |
|---|---|---|---|---|
| 31–25 | — | Reserved | 保留 | — |
| 24 | 0x01000000 |
SYSRAM | 内容来自系统 RAM(输出状态,非 mmap 入参) | 输出 |
| 23 | — | Reserved | 保留 | — |
| 22 | 0x00400000 |
PG_HWMAPPED | 页已被硬件映射过 | 内核页状态 |
| 21 | 0x00200000 |
PG_REFERENCED | 页被访问过(LRU 用) | 内核页状态 |
| 20 | 0x00100000 |
PG_MODIFIED | 页被改写过(脏页) | 内核页状态 |
| 19 | 0x00080000 |
ANON | 匿名内存,无文件后端 | QNX 扩展 |
| 18 | 0x00040000 |
BELOW16M | 物理地址低于 16M(ISA DMA) | QNX 扩展 |
| 17 | 0x00020000 |
NOX64K | 分配区不跨 64K 边界(老式 DMA) | QNX 扩展 |
| 16 | 0x00010000 |
PHYS | 物理内存;不带 ANON 时 offset 即物理地址 | QNX 扩展 |
| 15 | — | Reserved | 保留 | — |
| 14 | 0x00004000 |
NOINIT | 放宽"必须清零"的 POSIX 要求 | QNX 扩展 |
| 13 | 0x00002000 |
BELOW | addr 作下界向下搜索 | QNX 扩展 |
| 12 | 0x00001000 |
STACK | 告知分配器这匿名内存用作栈(仅提示) | QNX 扩展 |
| 11 | 0x00000800 |
PROT_NOCACHE | 禁缓存(双口内存、帧缓冲) | 保护位 |
| 10 | 0x00000400 |
PROT_EXEC | 可执行 | 保护位 |
| 9 | 0x00000200 |
PROT_WRITE | 可写 | 保护位 |
| 8 | 0x00000100 |
PROT_READ | 可读 | 保护位 |
| 7 | 0x00000080 |
LAZY | 延迟分配物理页,访问时才给(影响 rsv) | QNX 扩展 |
| 6 | 0x00000040 |
NOSYNCFILE | 改动不回写底层文件 | QNX 扩展 |
| 5 | 0x00000020 |
ELF | 该映射是 ELF 对象,由加载器设置 | QNX 扩展 |
| 4 | 0x00000010 |
FIXED | 必须落在指定 addr | POSIX |
| 3–2 | — | Reserved | 保留 | — |
| 1–0 | — | 类型字段 | 00 FILE / 01 SHARED / 10 PRIVATE / 11 PRIVATEANON | 类型 |
2.2 prot
也是按位掩码
0x01=R(只读)
0x02=W
0x04=X
0x08=NOCACHE
所以: 0x03=RW(读/写),0x05=RX(读/执行) ,0x07=RWX
2.3 ino
anon 对象(bss/heap/stack)的ino是3
| 映射 | 条数 | ino | dev |
|---|---|---|---|
{bss} ×7 |
7 | 0x3 |
0x1 |
{heap} |
1 | 0x3 |
0x1 |
{stack} |
1 | 0x3 |
0x1 |
| ELF 文件 | 各段 | 0x8000003d~0x80000046 |
0x802 |
/dev/shmem/* |
5 | 0xd251d8adec41…(64 位随机) |
0x1 |
2.4 offset
在对象内的起始偏移(code/bss=0;data=文件内偏移)
2.5 rsv
该区域为这个进程预留的物理内存,如果是共享数据(so库的code,shmem),不需要给这个进程预留内存,则rsv是0,如果需要预留内存(bss、data、heap、stack),则rsv是数据大小,和size的大小对应
2.6 path
后端对象名{bss}{heap}{stack}文件路径
2.7 asinfo
供页的地址空间段
{ram}=IFS 镜像在 RAM
{sysram}=系统 RAM 供页
3 pmap与mem对比
3.1 mem按地址排序
为方便对比,将pidin mem的数据按地址排序
| # | 地址 | 对象 | code | data | 类别 | 说明 |
|---|---|---|---|---|---|---|
| 1 | 0x01af522e000 |
/shmem/slogger2/console.16387 |
- | 20K | shmem | 簇①起 |
| 2 | 0x01af5233000 |
/dev/shmem/slogger2/devb_eide.53254 |
- | 68K | shmem | 紧邻 |
| 3 | 0x01af5244000 |
/shmem/slogger2/io_hid.118791 |
- | 68K | shmem | 紧邻 |
| 4 | 0x01af5255000 |
/dev/shmem/slogger2/devc_pty.200719 |
- | 68K | shmem | 紧邻 |
| 5 | 0x01af5266000 |
/shmem/slogger2/dhcpcd.266259 |
- | 68K | shmem | 紧邻 |
| 6 | 0x02806fb3000 |
ldqnx-64.so.2 |
224K | 12K | 库 | 簇②起 |
| 7 | 0x02806fee000 |
**zero ELF** |
- | 4K | bss | ← ldqnx |
| 8 | 0x02806fef000 |
libslog2.so.1 |
20K | 4K | 库 | 紧邻 |
| 9 | 0x02806ff4000 |
**zero ELF** |
- | 4K | bss | ← libslog2 |
| 10 | 0x02806ff6000 |
libsecpol.so.1 |
20K | 4K | 库 | 间隔 4K |
| 11 | 0x02806ffb000 |
**zero ELF** |
- | 4K | bss | ← libsecpol |
| 12 | 0x02806ffd000 |
libc.so.6 |
668K | 8K | 库 | 间隔 4K |
| 13 | 0x028070a4000 |
**zero ELF** |
- | 16K | bss | ← libc ① |
| 14 | 0x028070aa000 |
**zero ELF** |
- | 24K | bss | ← libc ②(中间夹 data 8K) |
| 15 | 0x028070b0000 |
libgcc_s.so.1 |
112K | 4K | 库 | 紧邻 |
| 16 | 0x028070cc000 |
**zero ELF** |
- | 4K | bss | ← libgcc |
| 17 | 0x0367cce0000 |
slogger2 |
64K | 8K | 本体 | 簇③ |
| 18 | 0x0367ccf2000 |
**zero ELF** |
- | 4K | bss | ← slogger2 |
| 19 | 0x05ddfc4c000 |
**heap** |
- | 84K | 堆 | 簇④ |
无地址信息的线程栈先列举到这里
pid tid name prio STATE code data stack
16387 1 proc/boot/slogger2 10r RECEIVE 1108K 476K 512K/512K
3.2 两者对比
将pmap表的一些字段的数据去掉,仅保留如下字段,并在右侧加一列“对应”pidin mem数据的序号列,根据两个表中的地址,以及对象名称/path,可以发现pidin mem数据的code和data,在这个pmap表中可以一一对应。这里用比如6-c表示对应第6行的code,6-d表示对应第6行的data,data可能分两段映射,所以可能会有两个6-d。
| vaddr | size | flags | prot | offset | rsv | path | 对应 |
|---|---|---|---|---|---|---|---|
| 0x1af522e000 | 0x05000(20K) | 0x20001 | 0x03 | 0x00000 | 0x00000 | ...ogger2/console.16387 | 1 |
| 0x1af5233000 | 0x11000(68K) | 0x00001 | 0x03 | 0x00000 | 0x00000 | ...ogger2/devb_eide.53254 | 2 |
| 0x1af5244000 | 0x11000(68K) | 0x00001 | 0x03 | 0x00000 | 0x00000 | ...ogger2/io_hid.118791 | 3 |
| 0x1af5255000 | 0x11000(68K) | 0x00001 | 0x03 | 0x00000 | 0x00000 | ...ogger2/devc_pty.200719 | 4 |
| 0x1af5266000 | 0x11000(68K) | 0x00001 | 0x03 | 0x00000 | 0x00000 | ...ogger2/dhcpcd.266259 | 5 |
| 0x2806fb3000 | 0x38000(224K) | 0x10031 | 0x05 | 0x00000 | 0x00000 | /proc/boot/ldqnx-64.so.2 | 6-c |
| 0x2806feb000 | 0x02000(8K) | 0x10032 | 0x01 | 0x37000(220K) | 0x02000 | /proc/boot/ldqnx-64.so.2 | 6-d |
| 0x2806fed000 | 0x01000(4K) | 0x10032 | 0x03 | 0x39000(228K) | 0x01000 | /proc/boot/ldqnx-64.so.2 | 6-d |
| 0x2806fee000 | 0x01000(4K) | 0x80032 | 0x03 | 0x00000 | 0x01000 | {bss} | 7 |
| 0x2806fef000 | 0x05000(20K) | 0x10031 | 0x05 | 0x00000 | 0x00000 | /proc/boot/libslog2.so.1 | 8-c |
| 0x2806ff4000 | 0x01000(4K) | 0x80032 | 0x01 | 0x00000 | 0x01000 | {bss} | 9 |
| 0x2806ff5000 | 0x01000(4K) | 0x10032 | 0x03 | 0x05000(20K) | 0x01000 | /proc/boot/libslog2.so.1 | 8-d |
| 0x2806ff6000 | 0x05000(20K) | 0x10031 | 0x05 | 0x00000 | 0x00000 | /proc/boot/libsecpol.so.1 | 10-c |
| 0x2806ffb000 | 0x01000(4K) | 0x80032 | 0x01 | 0x00000 | 0x01000 | {bss} | 11 |
| 0x2806ffc000 | 0x01000(4K) | 0x10032 | 0x03 | 0x05000(20K) | 0x01000 | /proc/boot/libsecpol.so.1 | 10-d |
| 0x2806ffd000 | 0xa7000(668K) | 0x10031 | 0x05 | 0x00000 | 0x00000 | /proc/boot/libc.so.6 | 12-c |
| 0x28070a4000 | 0x04000(16K) | 0x80032 | 0x01 | 0x00000 | 0x04000 | {bss} | 13 |
| 0x28070a8000 | 0x02000(8K) | 0x10032 | 0x03 | 0xaa000(680K) | 0x02000 | /proc/boot/libc.so.6 | 12-d |
| 0x28070aa000 | 0x06000(24K) | 0x80032 | 0x03 | 0x00000 | 0x06000 | {bss} | 14 |
| 0x28070b0000 | 0x1c000(112K) | 0x10031 | 0x05 | 0x00000 | 0x00000 | /proc/boot/libgcc_s.so.1 | 15-c |
| 0x28070cc000 | 0x01000(4K) | 0x80032 | 0x01 | 0x00000 | 0x01000 | {bss} | 16 |
| 0x28070cd000 | 0x01000(4K) | 0x10032 | 0x03 | 0x1d000(116K) | 0x01000 | /proc/boot/libgcc_s.so.1 | 15-d |
| 0x367cce0000 | 0x10000(64K) | 0x10031 | 0x05 | 0x00000 | 0x00000 | /proc/boot/slogger2 | 17-c |
| 0x367ccf0000 | 0x01000(4K) | 0x10032 | 0x01 | 0x0f000(60K) | 0x01000 | /proc/boot/slogger2 | 17-d |
| 0x367ccf1000 | 0x01000(4K) | 0x10032 | 0x03 | 0x10000(4K) | 0x01000 | /proc/boot/slogger2 | 17-d |
| 0x367ccf2000 | 0x01000(4K) | 0x80032 | 0x03 | 0x00000 | 0x01000 | {bss} | 18 |
| 0x403aeab000 | 0x80000(512K) | 0x81002 | 0x03 | 0x00000 | 0x80000 | {stack} | 线程栈 |
| 0x5ddfc4c000 | 0x15000(84K) | 0x80002 | 0x03 | 0x00000 | 0x15000 | {heap} | 19 |
3.2.1 观察到的现象
pidin mem的code和data数据在pmap中都有对应
flags列的16进制的最低位
是1:表示SHARED,则rsv列对应是0(不需要预留内存)
是2:表示PRIVATE,则rsv列与size列的大小一样(需要预留的内存大小)
flags列的16进制的低第2位
是0:对应共享内存(shmem)、stack、heap
是3:表示必须落在指定 addr的ELF,对应ELF对象、zero ELF
flags列的16进制的低第3位:都是0
flags列的16进制的低第4位
是0:除了stack行都是0是1:表示STACK,对应stack行flags列的16进制的低第5位
是1:表示PHYS,是2:表示NOX64K,是8:表示ANON,对应bss、stack、heap
port列:0x03:最多,读写,对应data0x05:可读、可执行,对应code0x01:只读,对应data(可以是ELF对象,也可以是bss),
每个0x05后面跟着一个0x01
3.2.2 offset列的理解
例子1
pidin mem的信息
| # | 地址 | 对象 | code | data | 类别 | 说明 |
|---|---|---|---|---|---|---|
| 8 | 0x02806fef000 |
libslog2.so.1 |
20K | 4K | 库 | 紧邻 |
| 9 | 0x02806ff4000 |
**zero ELF** |
- | 4K | bss | ← libslog2 |
0x02806fef000
-
- 地址有
libslog2.so.1
-
- 对象,该对象有20K的code和4K的data
0x02806ff4000与0x02806fef000相差0x5000,即20K,那这20K如何满足libslog2.so.1
- 对象的20K+4K
pmap的信息
| vaddr | size | flags | prot | offset | rsv | path | 对应 |
|---|---|---|---|---|---|---|---|
| 0x2806fef000 | 0x05000(20K) | 0x10031 | 0x05 | 0x00000 | 0x00000 | /proc/boot/libslog2.so.1 | 8-c |
| 0x2806ff4000 | 0x01000(4K) | 0x80032 | 0x01 | 0x00000 | 0x01000 | {bss} | 9 |
| 0x2806ff5000 | 0x01000(4K) | 0x10032 | 0x03 | 0x05000(20K) | 0x01000 | /proc/boot/libslog2.so.1 | 8-d |
把 libslog2.so.1 文件的第0 ~ 20K 映射到 0x2806fef000把 libslog2.so.1 文件的第20 ~ 24K 映射到 0x2806ff5000
例子2
pidin mem的信息
| # | 地址 | 对象 | code | data | 类别 | 说明 |
|---|---|---|---|---|---|---|
| 6 | 0x02806fb3000 |
ldqnx-64.so.2 |
224K | 12K | 库 | 簇②起 |
| 7 | 0x02806fee000 |
**zero ELF** |
- | 4K | bss | ← ldqnx |
0x02806fb3000
-
- 地址有
ldqnx-64.so.2
-
- 对象,该对象有224K的code和12K的data
0x02806fee000与0x02806fb3000相差0x3B000,即236K,正好满足ldqnx-64.so.2对象的224K+12K,那实际是不是这样呢
pmap的信息
| vaddr | size | flags | prot | offset | rsv | path | 对应 |
|---|---|---|---|---|---|---|---|
| 0x2806fb3000 | 0x38000(224K) | 0x10031 | 0x05(r/x) | 0x00000 | 0x00000 | /proc/boot/ldqnx-64.so.2 | 6-c |
| 0x2806feb000 | 0x02000(8K) | 0x10032 | 0x01(r) | 0x37000(220K) | 0x02000 | /proc/boot/ldqnx-64.so.2 | 6-d |
| 0x2806fed000 | 0x01000(4K) | 0x10032 | 0x03(r/w) | 0x39000(228K) | 0x01000 | /proc/boot/ldqnx-64.so.2 | 6-d |
| 0x2806fee000 | 0x01000(4K) | 0x80032 | 0x03 | 0x00000 | 0x01000 | {bss} | 7 |
4个地址的间隔是224K、8K、4K把/proc/boot/ldqnx-64.so.2文件的
第0 ~ 224K 映射到0x2806fb3000把/proc/boot/ldqnx-64.so.2文件的
第220 ~ 228K 映射到0x2806feb000把/proc/boot/ldqnx-64.so.2文件的
第228 ~ 232K 映射到0x2806fed000
注意,这里把220~224K连续映射了两次,最后的4K(data)没映射到,不过实际占用的空间还是236K。
ELF 加载时出现 "mapped twice",通常是因为文件里相邻段的边界正好落在同一页上,导致这一页被两个段重复映射,但权限不同。
这个映射两次的具体原因和作用,暂未探究明白,后续再讨论。
4 总结
本篇介绍了QNX进程中pmap数据的解读,并结合pidin mem的数据,分析其对应关系。
附:16进制大小对应表
| 16进程 | 10进制 | 大小 |
|---|---|---|
| 0x01000 | 4096 | 4K |
| 0x02000 | 8182 | 8K |
| 0x03000 | 12288 | 12K |
| 0x04000 | 16384 | 16K |
| 0x05000 | 20480 | 20K |
| 0x06000 | 24576 | 24K |
| 0x07000 | 28672 | 28K |
| 0x08000 | 32768 | 32K |
| 0x09000 | 36864 | 36K |
| 0x0a000 | 40960 | 40K |
| 0x0b000 | 45056 | 44K |
| 0x0c000 | 49152 | 48K |
| 0x0d000 | 53248 | 52K |
| 0x0e000 | 57344 | 56K |
| 0x0f000 | 61440 | 60K |
| 0x10000 | 65536 | 64K |
| 0x20000 | 131072 | 128K |
| 0x40000 | 262144 | 256K |
| 0x80000 | 524288 | 512K |
221