上篇介绍了如何在VirtualBox中安装QNX系统,本篇来探究QNX系统中pidin mem指令给出的信息中,进程的内存使用是如何表现的。
1 预备知识
在开始正式研究pidin mem指令之前,先了解些预备知识。
1.1 ELF
ELF = Executable and Linkable Format(可执行与可链接格式),它是Unix 系的可执行文件、共享库、目标文件(.o)统一用的容器格式。
一个 ELF 文件内部按 section(段) 组织:
| section | 装什么 | 在文件里 |
|---|---|---|
.text |
机器指令(编译后的代码) | 占空间 |
.rodata |
只读数据,字符串常量、const 全局量 |
占空间,通常和 .text 一起映射 |
.data |
已初始化且初值非零的全局/静态变量 | 占空间 |
.bss |
未初始化、或初值为 0 的全局/静态变量 | 占 0 字节 |
pidin 的 code 列 = .text + .rodata。
1.2 bss
bss = Block Started by Symbol ,1950 年代 IBM 704 上汇编器的一条伪指令名,意思是"从这里开始预留一块空间给符号"。
Unix 沿用了这个名字,现在指存放未初始化(或初值为 0)的全局变量和静态变量的那一段。
它装的是这些东西:
int g_buffer[4096]; // 未初始化 → .bss
static int counter = 0; // 初值为 0 → 编译器也塞进 .bss
int g_flag = 1; // 初值非零 → .data
为什么文件里不占空间:内容反正全是 0,存 4096 个零字节纯浪费,所以 ELF 只在 section header 里记一个"长度 16K",加载器看到就直接映射一段零页。这是 ELF 设计的经典取巧。
.bss 没有文件后端,加载器只能"凭空造一段全零的私有内存" —— pidin 把它显示为 **zero ELF**,名字取得很贴切:ELF 对象里那个"zero 的部分"。
简单说:ELF 是文件格式,bss 是它里面"不占磁盘、加载时现造一段零页"的那个段;pidin 把 ELF 的 text 报成 code、data 报成 data、bss 单独报成 **zero ELF** 。
2 pidin mem
输入pidin mem后,会有如下打印,会列举出所有的进程和线程,这里截图开头的部分
表头含义
| pid | tid | name | prio | STATE | code | data | stack |
|---|---|---|---|---|---|---|---|
| 进程号 | 线程号 | 名称 | 优先级+策略 | 状态 | 代码段 | 数据段 | 栈(已用/上限) |
如果想知道一共多少个进程和线程,可以用top指令看一下:
可以看到有25个进程和113个线程。
下面先来看pidin mem的每个进程的分析。
2.1 进程[1]procnto-smp-instr分析
procnto属于内核进程,procnto 是**“Process Neutrino”**的缩写,即 QNX Neutrino 微内核与进程管理器的组合模块
pid tid name prio STATE code data stack
1 1 /proc/boot/procnto-smp-instr 0f READY 788K 157K 28K/164K
1 2 /proc/boot/procnto-smp-instr 0f READY 788K 157K 28K/164K
1 3 /proc/boot/procnto-smp-instr 255i INTR 788K 157K 0/164K
1 4 /proc/boot/procnto-smp-instr 255i INTR 788K 157K 0/164K
1 5 /proc/boot/procnto-smp-instr 254i INTR 788K 157K 0/164K
1 6 /proc/boot/procnto-smp-instr 254i INTR 788K 157K 0/164K
1 7 /proc/boot/procnto-smp-instr 1f NANOSLEEP 788K 157K 0/164K
1 8 /proc/boot/procnto-smp-instr 10r ??? 788K 157K 12K/164K
1 9 /proc/boot/procnto-smp-instr 10r RECEIVE 788K 157K 12K/164K
1 10 /proc/boot/procnto-smp-instr 10r RECEIVE 788K 157K 12K/164K
1 11 /proc/boot/procnto-smp-instr 10r RECEIVE 788K 157K 12K/164K
1 12 /proc/boot/procnto-smp-instr 10r RECEIVE 788K 157K 12K/164K
1 13 /proc/boot/procnto-smp-instr 11r RECEIVE 788K 157K 12K/164K
1 14 /proc/boot/procnto-smp-instr 10r RUNNING 788K 157K 12K/164K
1 15 /proc/boot/procnto-smp-instr 10r RECEIVE 788K 157K 12K/164K
1 16 /proc/boot/procnto-smp-instr 10r RECEIVE 788K 157K 12K/164K
procnto-smp-instr @ffff800000001000 788K 157K
stack总计:28x2 + 12x9 = 56 + 108 = 164K ✓
2.1.1 逐行分析
第一行
1 1 /proc/boot/procnto-smp-instr 0f READY 788K 157K 28K/164K
根据表头,对比来看
| 字段 | 值 | 含义 |
|---|---|---|
| pid/tid | 1 / 1 |
进程ID/线程ID,procnto 永远是 pid 1,它把微内核和进程管理器打在一个进程里 |
| prio | 0f |
优先级 0(最低,只有 idle 线程用)+ f = FIFO 调度 |
| STATE | READY |
就绪 |
| code/data | 788K / 157K |
代码段、数据段的大小,进程级 |
| stack | 28K/164K |
线程栈,当前线程栈 28K,进程中所有线程栈累计164K(进程的上限) |
所有行对比看
这些线程的 prio/STATE/已用stack 逐个看:
| tid | prio | STATE | 线程stack | 说明 |
|---|---|---|---|---|
| 1, 2 | 0f |
READY | 28K | idle 线程,每个 CPU 一个(这台机器 2 核) |
| 3, 4 | 255i |
INTR | 0 | 中断线程,i 表示中断上下文,255 是最高优先级 |
| 5, 6 | 254i |
INTR | 0 | 中断线程,254 稍低 |
| 7 | 1f |
NANOSLEEP | 0 | 内核定时器线程 |
| 8 | 10r |
??? |
12K | 内核内部线程,pidin 认不出状态,正常现象 |
| 9-13, 15, 16 | 10r |
RECEIVE | 12K | 阻塞在消息接收的服务线程(tid 13 是 11r,优先级 11) |
| 14 | 10r |
RUNNING | 12K | 抓样瞬间正在跑 |
最后一行
最后一行,是 procnto 的映射明细行(缩进、带 @地址)
procnto-smp-instr @ffff800000001000 788K 157K
注意地址 0xffff800000001000 —— x86-64 上 0xffff8... 开头是内核地址空间,印证了 procnto 的代码/数据运行在内核半区,而不是普通用户态地址(0x2ada... 那种)。
而且它只有这一条映射,没有 libc 等共享库,说明 procnto 是静态自包含的镜像。
2.1.2 总结procnto
procnto-smp-instr(pid 1)是微内核与进程管理器的合体。
那 16 行打印的是它的 16 个线程而非 16 份内存 —— code 788K、data 157K 每行都相同、只能算一次。
唯一一条映射行落在内核地址空间 0xffff800000001000 且没有任何共享库依赖。
整个"内核"只占 1109K。
| 组成 | 数值 | 来源 |
|---|---|---|
| code | 788K | 映射行第 2 列,进程级 |
| data | 157K | 映射行第 3 列,进程级 |
| 栈 | 164K | 28K×2 + 0×5 + 12K×9,逐线程相加 |
| 合计 | 1109K |
2.2 进程[13687]slogger2分析
slogger2是系统日志服务(system logger service),它只有一个 tid → 单线程进程。
10r RECEIVE 是服务器的标准姿势:阻塞在 MsgReceive() 等客户端请求。
16387 1 proc/boot/slogger2 10r RECEIVE 1108K 476K 512K/512K
slogger2 @2ada120000 64K 8192
ldqnx-64.so.2 @4ab6994000 224K 12K
libslog2.so.1 @4ab69d0000 20K 4096
libsecpol.so.1 @4ab69d7000 20K 4096
libc.so.6 @4ab69de000 668K 8192
libgcc_s.so.1 @4ab6a91000 112K 4096
**heap** @18eaa81000 ( 0) 84K
**zero ELF** @2ada132000 ( 0) 4096
/shmem/slogger2/console.16387 @301f2ad000 ( 0) 20K
hmem/slogger2/devb_eide.53254 @301f2b2000 ( 0) 68K
/shmem/slogger2/io_hid.118791 @301f2c3000 ( 0) 68K
hmem/slogger2/devc_pty.200719 @301f2d4000 ( 0) 68K
/shmem/slogger2/dhcpcd.266259 @301f2e5000 ( 0) 68K
**zero ELF** @4ab69cf000 ( 0) 4096
**zero ELF** @4ab69d5000 ( 0) 4096
**zero ELF** @4ab69dc000 ( 0) 4096
**zero ELF** @4ab6a85000 ( 0) 16K
**zero ELF** @4ab6a8b000 ( 0) 24K
**zero ELF** @4ab6aad000 ( 0) 4096
2.2.1 映射行的两种格式
后面的映射行有两种格式
格式 A —— 可执行文件与共享库
code 和 data 各占一列
slogger2 @2ada120000 64K 8192
| 对象名 | 加载地址 | code | data |
|---|---|---|---|
| slogger2 | @2ada120000 | 64K | 8192 |
| 可执行文件自身 | 用户态虚拟地址 | 只读可执行段 .text | 可写数据段,8K |
格式 B
格式一样,实际作用又可分为三类
- heap,堆shmem,共享内存zero ELF,零页
code 写进括号里,只剩一列 size
**heap** @18eaa81000 ( 0) 84K
| 对象名 | 加载地址 | offset(括号内) | size |
|---|---|---|---|
**heap** |
@18eaa81000 | 0 | 84K |
| 双星号包裹 = 匿名内存 | 虚拟地址 | mmap的偏移量 | 末列即 data,计入总数 |
判断方法:
- 行内出现左圆括号就是格式 B,此时 code = 括号里的数(通常为 0),末列解析为 data否则末两列分别是 code 和 data
2.2.2 对19 条映射行逐条分析
2.2.2.1 ELF对象
前 6 条是 ELF 对象(格式 A,可执行文件 + 5 个共享库)
| 行 | 对象 | code | data | 说明 |
|---|---|---|---|---|
| 1 | slogger2 |
64K | 8K | 可执行文件本体,text 只有 64K |
| 2 | ldqnx-64.so.2 |
224K | 12K | 动态链接器,每个进程都加载 |
| 3 | libslog2.so.1 |
20K | 4K | 日志库 |
| 4 | libsecpol.so.1 |
20K | 4K | 安全策略库 |
| 5 | libc.so.6 |
668K | 8K | code 的大头,占 60% |
| 6 | libgcc_s.so.1 |
112K | 4K | GCC 运行时 |
2.2.2.2 格式B部分
堆
**heap** @18eaa81000 ( 0) 84K
第 7 条是堆(格式 B):**heap** 84K —— malloc 分配来的
共享内存
第 9–13 条注意名字被截断了:
/shmem/slogger2/console.16387 @301f2ad000 ( 0) 20K
hmem/slogger2/devb_eide.53254 @301f2b2000 ( 0) 68K
/shmem/slogger2/io_hid.118791 @301f2c3000 ( 0) 68K
hmem/slogger2/devc_pty.200719 @301f2d4000 ( 0) 68K
/shmem/slogger2/dhcpcd.266259 @301f2e5000 ( 0) 68K
name 列固定约 29 字符宽,超长从左边截。
比如这两行的真名分别是
/dev/shmem/slogger2/console.16387/dev/shmem/slogger2/devb_eide.53254
这是 slogger2 给每个日志客户端开的共享缓冲区,68K 是默认尺寸,名字里的数字就是客户端 pid。
bss(zero ELF)
第8条-slogger2 本体的 bss
**zero ELF** @2ada132000 ( 0) 4096
第14~19条-各共享库的 bss
全是 **zero ELF**,也就是各 ELF 的 .bss(未初始化数据,文件里不占空间,加载时要匿名内存)。
2.2.3 按地址排序分析
可以将ELF对象与bss按地址进行排序:
| # | 地址 | 对象 | code | data | 类别 | 说明 |
|---|---|---|---|---|---|---|
| 1 | 0x18eaa81000 |
**heap** |
(0) | 84K | 堆 | 簇①,孤立 |
| 2 | 0x2ada120000 |
slogger2 |
64K | 8K | 主程序 | 簇② 起 |
| 3 | 0x2ada132000 |
**zero ELF** |
(0) | 4K | bss | 属 slogger2(+64K+8K 吻合) |
| 4 | 0x301f2ad000 |
/shmem/…/console.16387 |
(0) | 20K | shmem | 簇③ 起 |
| 5 | 0x301f2b2000 |
/shmem/…/devb_eide.53254 |
(0) | 68K | shmem | 紧邻上条 |
| 6 | 0x301f2c3000 |
/shmem/…/io_hid.118791 |
(0) | 68K | shmem | 紧邻 |
| 7 | 0x301f2d4000 |
/shmem/…/devc_pty.200719 |
(0) | 68K | shmem | 紧邻 |
| 8 | 0x301f2e5000 |
/shmem/…/dhcpcd.266259 |
(0) | 68K | shmem | 紧邻 |
| 9 | 0x4ab6994000 |
ldqnx-64.so.2 |
224K | 12K | 共享库 | 簇④ 起 |
| 10 | 0x4ab69cf000 |
**zero ELF** |
(0) | 4K | bss | 属 ldqnx(+224K+12K) |
| 11 | 0x4ab69d0000 |
libslog2.so.1 |
20K | 4K | 共享库 | |
| 12 | 0x4ab69d5000 |
**zero ELF** |
(0) | 4K | bss | 属 libslog2(+20K) |
| 13 | 0x4ab69d7000 |
libsecpol.so.1 |
20K | 4K | 共享库 | |
| 14 | 0x4ab69dc000 |
**zero ELF** |
(0) | 4K | bss | 属 libsecpol(+20K) |
| 15 | 0x4ab69de000 |
libc.so.6 |
668K | 8K | 共享库 | |
| 16 | 0x4ab6a85000 |
**zero ELF** |
(0) | 16K | bss | libc 第一段(+668K) |
| 17 | 0x4ab6a8b000 |
**zero ELF** |
(0) | 24K | bss | libc 第二段,末尾正好接 libgcc |
| 18 | 0x4ab6a91000 |
libgcc_s.so.1 |
112K | 4K | 共享库 | |
| 19 | 0x4ab6aad000 |
**zero ELF** |
(0) | 4K | bss | 属 libgcc(+112K) |
简单分析下slogger2
地址是 0x2ada120000,code是64k,data是8k它的zero ELF的地址是0x2ada132000
两地址相减,0x32000 - 0x20000 = 0x12000,十进制73728,也就是72K,即slogger2的data和zero ELF是紧邻的
再来看下libc.so.6,注意到,libc的bss是拆成两段
libc.so.6地址是0x4ab69de000,code是668k,data是8k第一个zero ELF地址是0x4ab6a85000,自身16K与libc的地址相减是0x0a7000,十进制684032,也就是668K,即这个zero ELF是跟在libc的code之后的
第二个zero ELF地址是0x4ab6a8b000,自身24K与第一个zero ELF地址相减是0x6000,十进制24576,也就是24K,而第一个zero ELF自身只有16K
注意到libc的data是8K,这8K没有分析到具体位置,可以猜想,两个zero ELF中间的8K,可能就是libc的data的位置
2.2.4 求和验算
code: 64 + 224 + 20 + 20 + 668 + 112 = 1108K ← 等于进程行 code ✓
data: 40K(6个对象的data: 8K + 12K + 4K + 4K + 8K + 4K) + 84K(heap)
+ 292K(shmem: 20K + 68K×4)
+ 60K(zero ELF 7条: 16K + 24K + 4K×5) = 476K ← 等于进程行 data ✓
2.2.5 总结slogger2
slogger2 这个进程,pidin mem给出的内存占用情况是:
code:1108K(1044K 来自共享库,只有 64K 是它自己)data:476K ELF对象40K:slogger2的8K + so库的32Kheap 84K 共享内存292Kbss(zero ELF) 60K stack:512K
总计占用内存:1108 + 476 + 512 = 2096K
如何是考虑进程自身单独的,比如去除code中共享库,去除data中的共享内存,可以是 760K(64K 自身code + 40K ELF对象data + 84K heap + 60K bss + 512K stack)
2.3 进程[28676]pci-server分析
它是PCI 服务进程,全称即 PCI Server,负责核心的 PCI 总线与设备管理服务
28676 1 proc/boot/pci-server 10r RECEIVE 1452K 684K 256K/1024K
28676 2 proc/boot/pci-server 10r RECEIVE 1452K 684K 256K/1024K
28676 3 proc/boot/pci-server 21r RECEIVE 1452K 684K 256K/1024K
28676 4 proc/boot/pci-server 10r RECEIVE 1452K 684K 256K/1024K
pci-server @35d2837000 156K 8192
ldqnx-64.so.2 @25c846a000 224K 12K
libpci.so.3.0 @25c84a6000 136K 16K
libsecpol.so.1 @25c84ce000 20K 4096
libc.so.6 @25c84d5000 668K 8192
libgcc_s.so.1 @25c8588000 112K 4096
pci_slog2.so.3.0 @25c85a6000 8192 4096
libslog2.so.1 @25c85aa000 20K 4096
pci_debug2.so.3.0 @25c85b1000 4096 4096
pci_hw-Intel_x86.so.3.1 @25c85b4000 104K 4096
mem/slogger2/pci_server.28676 @145ebf2000 ( 0) 68K
/dev/shmem/pci/pci_hw @145ec03000 ( 0) 4096
/slogger2/pci_server.28676..0 @145ec04000 ( 0) 68K
/dev/shmem/pci/pci_db @145ec15000 ( 0) 36K
/dev/shmem/pci/pci_sync @145ec1e000 ( 0) 4096
**zero ELF** @25c84a5000 ( 0) 4096
**zero ELF** @25c84c8000 ( 0) 8192
**zero ELF** @25c84d3000 ( 0) 4096
**zero ELF** @25c857c000 ( 0) 16K
**zero ELF** @25c8582000 ( 0) 24K
**zero ELF** @25c85a4000 ( 0) 4096
**zero ELF** @25c85a8000 ( 0) 4096
**zero ELF** @25c85af000 ( 0) 4096
**zero ELF** @25c85b2000 ( 0) 4096
**zero ELF** @25c85ce000 ( 0) 4096
**zero ELF** @25c85d0000 ( 0) 64K
**heap** @50641ae000 ( 0) 28K
**heap** @50641b5000 ( 0) 4096
**heap** @50641b6000 ( 0) 264K
2.3.1 有4个进程
28676 1 proc/boot/pci-server 10r RECEIVE 1452K 684K 256K/1024K
28676 2 proc/boot/pci-server 10r RECEIVE 1452K 684K 256K/1024K
28676 3 proc/boot/pci-server 21r RECEIVE 1452K 684K 256K/1024K
28676 4 proc/boot/pci-server 10r RECEIVE 1452K 684K 256K/1024K
tid 3 是 21r,比另外三个 10r 高—— 这是 PCI 的配置访问/中断响应线程,必须抢在其他工作线程前面。
stack总计:256x4 = 1024K ✓
2.3.2 有10个ELF对象
| 对象 | code | data | 性质 |
|---|---|---|---|
| pci-server | 156K | 8K | 自己 |
| libc.so.6 | 668K | 8K | 通用 |
| ldqnx-64.so.2 | 224K | 12K | 通用 |
| libpci.so.3.0 | 136K | 16K | PCI 专用 |
| libgcc_s.so.1 | 112K | 4K | 通用 |
| pci_hw-Intel_x86.so.3.1 | 104K | 4K | PCI 硬件驱动模块 |
| libsecpol.so.1 | 20K | 4K | 通用 |
| libslog2.so.1 | 20K | 4K | 通用 |
| pci_slog2.so.3.0 | 8K | 4K | PCI 专用 |
| pci_debug2.so.3.0 | 4K | 4K | PCI 专用 |
| 小计 | 1452K ✓ | 68K |
自己的 code 只占 156K,libc 一个就占668K。
2.3.3 格式B部分
共享内存
共享内存 180K(5 条,其中 2 条名字被左截断):
mem/slogger2/pci_server.28676 → /dev/shmem/slogger2/pci_server.28676 68K
/slogger2/pci_server.28676..0 → /dev/shmem/slogger2/pci_server.28676..0 68K
/dev/shmem/pci/pci_db 36K
/dev/shmem/pci/pci_hw 4K
/dev/shmem/pci/pci_sync 4K
小计:68 + 68 + 36 + 4 + 4 = 180
bss(zero ELF)
bss 140K:11 条 **zero ELF**。
**zero ELF** @25c84a5000 ( 0) 4096
**zero ELF** @25c84c8000 ( 0) 8192
**zero ELF** @25c84d3000 ( 0) 4096
**zero ELF** @25c857c000 ( 0) 16K
**zero ELF** @25c8582000 ( 0) 24K
**zero ELF** @25c85a4000 ( 0) 4096
**zero ELF** @25c85a8000 ( 0) 4096
**zero ELF** @25c85af000 ( 0) 4096
**zero ELF** @25c85b2000 ( 0) 4096
**zero ELF** @25c85ce000 ( 0) 4096
**zero ELF** @25c85d0000 ( 0) 64K
小计:4 + 8 + 4 + 16 + 24 + 4*5 + 64 = 140
堆
堆 296K:3 条。
**heap** @50641ae000 ( 0) 28K
**heap** @50641b5000 ( 0) 4096
**heap** @50641b6000 ( 0) 264K
小计:28 + 4 + 264 = 296
data总计:68(库data)+ 180(shmem)+ 140(bss)+ 296(heap)= 684K ✓
2.3.4 按地址排序分析
| # | 地址 | GiB | 对象 | code | data | 类别 | 说明 |
|---|---|---|---|---|---|---|---|
| 1 | 0x145ebf2000 |
81.5 | /dev/shmem/slogger2/pci_server.28676 |
(0) | 68K | shmem | 簇① 起 |
| 2 | 0x145ec03000 |
81.5 | /dev/shmem/pci/pci_hw |
(0) | 4K | shmem | 紧邻 |
| 3 | 0x145ec04000 |
81.5 | /dev/shmem/slogger2/pci_server.28676..0 |
(0) | 68K | shmem | 紧邻 |
| 4 | 0x145ec15000 |
81.5 | /dev/shmem/pci/pci_db |
(0) | 36K | shmem | 紧邻 |
| 5 | 0x145ec1e000 |
81.5 | /dev/shmem/pci/pci_sync |
(0) | 4K | shmem | 紧邻 |
| 6 | 0x25c846a000 |
151.1 | ldqnx-64.so.2 |
224K | 12K | 库 | 簇② 起 |
| 7 | 0x25c84a5000 |
151.1 | **zero ELF** |
(0) | 4K | bss | 属 ldqnx(+224K+12K) |
| 8 | 0x25c84a6000 |
151.1 | libpci.so.3.0 |
136K | 16K | 库 | |
| 9 | 0x25c84c8000 |
151.1 | **zero ELF** |
(0) | 8K | bss | 属 libpci(+136K) |
| 10 | 0x25c84ce000 |
151.1 | libsecpol.so.1 |
20K | 4K | 库 | |
| 11 | 0x25c84d3000 |
151.1 | **zero ELF** |
(0) | 4K | bss | 属 libsecpol(+20K) |
| 12 | 0x25c84d5000 |
151.1 | libc.so.6 |
668K | 8K | 库 | |
| 13 | 0x25c857c000 |
151.1 | **zero ELF** |
(0) | 16K | bss | libc ①(+668K) |
| 14 | 0x25c8582000 |
151.1 | **zero ELF** |
(0) | 24K | bss | libc ②(末接 libgcc) |
| 15 | 0x25c8588000 |
151.1 | libgcc_s.so.1 |
112K | 4K | 库 | |
| 16 | 0x25c85a4000 |
151.1 | **zero ELF** |
(0) | 4K | bss | 属 libgcc(+112K) |
| 17 | 0x25c85a6000 |
151.1 | pci_slog2.so.3.0 |
8K | 4K | 库 | |
| 18 | 0x25c85a8000 |
151.1 | **zero ELF** |
(0) | 4K | bss | 属 pci_slog2(+8K) |
| 19 | 0x25c85aa000 |
151.1 | libslog2.so.1 |
20K | 4K | 库 | |
| 20 | 0x25c85af000 |
151.1 | **zero ELF** |
(0) | 4K | bss | 属 libslog2(+20K) |
| 21 | 0x25c85b1000 |
151.1 | pci_debug2.so.3.0 |
4K | 4K | 库 | |
| 22 | 0x25c85b2000 |
151.1 | **zero ELF** |
(0) | 4K | bss | 属 pci_debug2(+4K) |
| 23 | 0x25c85b4000 |
151.1 | pci_hw-Intel_x86.so.3.1 |
104K | 4K | 库 | |
| 24 | 0x25c85ce000 |
151.1 | **zero ELF** |
(0) | 4K | bss | pci_hw ①(+104K) |
| 25 | 0x25c85d0000 |
151.1 | **zero ELF** |
(0) | 64K | bss | pci_hw ②(中间夹 data 4K) |
| 26 | 0x35d2837000 |
215.3 | pci-server |
156K | 8K | 本体 | 簇③,孤立 |
| 27 | 0x50641ae000 |
321.6 | **heap** |
(0) | 28K | 堆 | 簇④ 起 |
| 28 | 0x50641b5000 |
321.6 | **heap** |
(0) | 4K | 堆 | 紧邻 |
| 29 | 0x50641b6000 |
321.6 | **heap** |
(0) | 264K | 堆 | 紧邻 |
注意到:
- pci-server 自没有独立 bss(它的 data 8K 已涵盖)libc 和 pci_hw 各拆两段pci_hw 那 64K 是最大的单条 bss,应该是 Intel x86 PCI 控制器的设备表缓存堆 296K 是三段首尾相接,实际是一整块 296K 堆区被拆成三条列出(多半是不同分配批次或权限)
@50641ae000 28K ─┐
@50641b5000 4K ├─ 0x50641ae000 + 28K = 0x50641b5000 ✓
@50641b6000 264K ─┘ 0x50641b5000 + 4K = 0x50641b6000 ✓
2.4 进程[49157]fsevmgr分析
fsevmgr 全称可能是 Flash Storage Event Manager(闪存存储事件管理器)
49157 1 proc/boot/fsevmgr 10r SIGWAITINFO 1176K 228K 512K/584K
49157 2 proc/boot/fsevmgr 10r RECEIVE 1176K 228K 24K/584K
49157 3 proc/boot/fsevmgr 10r RECEIVE 1176K 228K 24K/584K
49157 4 proc/boot/fsevmgr 10r RECEIVE 1176K 228K 24K/584K
fsevmgr @246afdd000 24K 8192
ldqnx-64.so.2 @313fd8b000 224K 12K
libfsnotify.so.1 @313fdc7000 40K 12K
libqh.so.1 @313fdd5000 68K 4096
libslog2.so.1 @313fde9000 20K 4096
libsecpol.so.1 @313fdf0000 20K 4096
libc.so.6 @313fdf7000 668K 8192
libgcc_s.so.1 @313feaa000 112K 4096
**heap** @1a1fd8e000 ( 0) 92K
**zero ELF** @313fdc6000 ( 0) 4096
**zero ELF** @313fdd1000 ( 0) 4096
**zero ELF** @313fde6000 ( 0) 8192
**zero ELF** @313fdee000 ( 0) 4096
**zero ELF** @313fdf5000 ( 0) 4096
**zero ELF** @313fe9e000 ( 0) 16K
**zero ELF** @313fea4000 ( 0) 24K
**zero ELF** @313fec6000 ( 0) 4096
/shmem/slogger2/fsevmgr.49157 @428025e000 ( 0) 12K
2.4.1 求和验算
code总计:24 + 224 + 40 + 68 + 20 + 20 + 668 + 112 = 288 + 108 + 780 = 1176K ✓
data总计:228K ✓
- ELF对象:8 + 12 + 4 + 4 + 12 + 4 + 4 + 8 = 56K格式B部分:92 + 4*5 + 8 + 16 + 24 + 12 = 172K
stack总计:512 + 24x3 = 512 + 72 = 584K ✓
2.4.2 按地址排序分析
| # | 地址 | 对象 | code | data | 类别 | 说明 |
|---|---|---|---|---|---|---|
| 1 | 0x01a1fd8e000 |
**heap** |
(0) | 92K | 堆 | 簇①起 |
| 2 | 0x0246afdd000 |
fsevmgr |
24K | 8K | 本体 | 新簇,孤立 |
| 3 | 0x0313fd8b000 |
ldqnx-64.so.2 |
224K | 12K | 库 | 簇③起 |
| 4 | 0x0313fdc6000 |
**zero ELF** |
(0) | 4K | bss | ← ldqnx |
| 5 | 0x0313fdc7000 |
libfsnotify.so.1 |
40K | 12K | 库 | 紧邻 |
| 6 | 0x0313fdd1000 |
**zero ELF** |
(0) | 4K | bss | ← libfsnotify |
| 7 | 0x0313fdd5000 |
libqh.so.1 |
68K | 4K | 库 | 间隔 12K(= 上条 data) |
| 8 | 0x0313fde6000 |
**zero ELF** |
(0) | 8K | bss | ← libqh |
| 9 | 0x0313fde9000 |
libslog2.so.1 |
20K | 4K | 库 | 间隔 4K |
| 10 | 0x0313fdee000 |
**zero ELF** |
(0) | 4K | bss | ← libslog2 |
| 11 | 0x0313fdf0000 |
libsecpol.so.1 |
20K | 4K | 库 | 间隔 4K |
| 12 | 0x0313fdf5000 |
**zero ELF** |
(0) | 4K | bss | ← libsecpol |
| 13 | 0x0313fdf7000 |
libc.so.6 |
668K | 8K | 库 | 间隔 4K |
| 14 | 0x0313fe9e000 |
**zero ELF** |
(0) | 16K | bss | ← libc ① |
| 15 | 0x0313fea4000 |
**zero ELF** |
(0) | 24K | bss | ← libc ②(中间夹 data 8K) |
| 16 | 0x0313feaa000 |
libgcc_s.so.1 |
112K | 4K | 库 | 紧邻 |
| 17 | 0x0313fec6000 |
**zero ELF** |
(0) | 4K | bss | ← libgcc |
| 18 | 0x0428025e000 |
/shmem/slogger2/fsevmgr.49157 |
(0) | 12K | shmem | 新簇,孤立 |
2.5 进程[53254]devb-eide分析
devb-eide 的全称是 Device Block Enhanced IDE Driver,即增强型 IDE 块设备驱动。它负责管理 IDE/ATA 接口的硬盘和光驱等设备。
53254 1 proc/boot/devb-eide 10r SIGWAITINFO 2084K 67M 64K/308K
53254 2 proc/boot/devb-eide 21r RECEIVE 2084K 67M 16K/308K
53254 3 proc/boot/devb-eide 254i INTR 2084K 67M 0/308K
53254 4 proc/boot/devb-eide 21r RECEIVE 2084K 67M 20K/308K
53254 5 proc/boot/devb-eide 10r RECEIVE 2084K 67M 24K/308K
53254 6 proc/boot/devb-eide 10r RECEIVE 2084K 67M 24K/308K
53254 7 proc/boot/devb-eide 10r RECEIVE 2084K 67M 20K/308K
53254 8 proc/boot/devb-eide 10r RECEIVE 2084K 67M 20K/308K
53254 9 proc/boot/devb-eide 10r RECEIVE 2084K 67M 20K/308K
53254 10 proc/boot/devb-eide 10r RECEIVE 2084K 67M 20K/308K
53254 11 proc/boot/devb-eide 10r RECEIVE 2084K 67M 20K/308K
53254 12 proc/boot/devb-eide 10r RECEIVE 2084K 67M 20K/308K
53254 13 proc/boot/devb-eide 10r RECEIVE 2084K 67M 20K/308K
53254 14 proc/boot/devb-eide 10r RECEIVE 2084K 67M 20K/308K
devb-eide @4ada4c5000 116K 12K
ldqnx-64.so.2 @1226756000 224K 12K
libsecpol.so.1 @1226792000 20K 4096
libslog2.so.1 @1226799000 20K 4096
libcam.so.2 @12267a0000 96K 4096
libc.so.6 @12267ba000 668K 8192
libgcc_s.so.1 @122686d000 112K 4096
io-blk.so @122688b000 288K 12K
libfsnotify.so.1 @12268d8000 40K 12K
pci_bkwd_compat.so.3.0 @12268e6000 16K 4096
libpci.so.3.0 @12268ec000 136K 16K
pci_slog2.so.3.0 @1226914000 8192 4096
pci_hw-Intel_x86.so.3.1 @1226918000 104K 4096
cam-disk.so @1226944000 12K 4096
fs-qnx6.so @1226949000 224K 4096
**zero ELF** @1226791000 ( 0) 4096
**zero ELF** @1226797000 ( 0) 4096
**zero ELF** @122679e000 ( 0) 4096
**zero ELF** @12267b8000 ( 0) 4096
**zero ELF** @1226861000 ( 0) 16K
**zero ELF** @1226867000 ( 0) 24K
**zero ELF** @1226889000 ( 0) 4096
**zero ELF** @12268d3000 ( 0) 8192
**zero ELF** @12268e2000 ( 0) 4096
**zero ELF** @12268ea000 ( 0) 4096
**zero ELF** @122690e000 ( 0) 8192
**zero ELF** @1226916000 ( 0) 4096
**zero ELF** @1226932000 ( 0) 4096
**zero ELF** @1226934000 ( 0) 64K
**zero ELF** @1226947000 ( 0) 4096
**zero ELF** @1226981000 ( 0) 4096
m/slogger2/devb_eide.53254..0 @2afa750000 ( 0) 68K
m/slogger2/devb_eide.53254..1 @2afa761000 ( 0) 68K
/dev/shmem/pci/pci_db @2afa772000 ( 0) 36K
/dev/shmem/pci/pci_sync @2afa77b000 ( 0) 4096
/dev/shmem/pci/pci_hw @2afa77c000 ( 0) 4096
**anonymous** @2afa77d000 ( 0) 4096
sysram&below4G @2afa77e000 ( 0) 4096
sysram&below4G @2afa77f000 ( 0) 4096
**anonymous** @2afa780000 ( 0) 64M
sysram&below4G @2afe790000 ( 0) 4096
**heap** @3072480000 ( 0) 44K
**heap** @307248b000 ( 0) 4096
**heap** @307248c000 ( 0) 2616K
**heap** @307271b000 ( 0) 244K
**heap** @3072759000 ( 0) 92K
**heap** @3072774000 ( 3000) 204K
2.5.1 求和验算
code总计:116 + 224 + 40 + 96 + 668 + 112 + 288 + 56 + 136 + 8 + 104 + 236 = 2084K ✓
data总计:108 + 164 + 172 + 4 + 64M + 12 + 3204 = 3664K + 64M = 67.58M = 67M ✓
ELF对象:12x4 + 4x9 + 8 + 16 = 108K
格式B部分
zero ELF:4x11 + 16 + 24 + 8x2 + 64 = 164K
共享内存:68x2 + 36 + 4x2 = 172K
**anonymous**:4 + 64M
sysram&below4G:4x3 = 12K
heap:44 + 4 + 2616 + 244 + 92 + 204 = 3204K
注意这里pidin mem显示的data是M单位,应该是取整了,67M,手动累加的是67.58M
stack总计:64 + 16 + 20x9 + 24X2 = 80 + 180 + 48 = 308K ✓
2.5.2 格式B新增的两种数据
另外这里多了两种数据:
sysram&below4G
不是 shmem 也不是匿名 —— 是物理内存的直通映射(devb-eide 做 DMA 必须能访问 4G 以下的物理地址,驱动把物理页直接映射进自己的地址空间)。三条各 4K,两条紧贴 64M 块、一条孤立在 64K 之外。
anonymous
一次性预分配,全系统最大的单块进程内存。它和前面的 shmem、sysram 是零间隙紧邻的(第 38 条结束地址正好是它的基址)。
2.5.3 格式B括号中的非0值
注意到,之前的格式B的括号中都是0,这次这个heap中不是0
**heap** @3072774000 ( 3000) 204K
这种非0的在后面的proc/boot/devc-con进程中也存在,是在memory这条中:
139272 1 proc/boot/devc-con 10r RECEIVE 1116K 176K 512K/512K
139272 2 proc/boot/devc-con 254i INTR 1116K 176K 0/512K
devc-con @1fef20b000 92K 8192
ldqnx-64.so.2 @303a8e9000 224K 12K
libsecpol.so.1 @303a925000 20K 4096
libc.so.6 @303a92c000 668K 8192
libgcc_s.so.1 @303a9df000 112K 4096
**zero ELF** @1fef224000 ( 0) 4096
memory @27b7d45000 ( 0) 4096
memory @27b7d46000 ( b8000) 32K
**zero ELF** @303a924000 ( 0) 4096
**zero ELF** @303a92a000 ( 0) 4096
**zero ELF** @303a9d3000 ( 0) 16K
**zero ELF** @303a9d9000 ( 0) 24K
**zero ELF** @303a9fb000 ( 0) 4096
**heap** @5bc2980000 ( 0) 84K
2.5.4 按地址排序分析
| # | 地址 | 对象 | code | data | 类别 | 说明 |
|---|---|---|---|---|---|---|
| 1 | 0x1226756000 |
ldqnx-64.so.2 |
224K | 12K | 库 | 簇①起 |
| 2 | 0x1226791000 |
**zero ELF** |
(0) | 4K | bss | ← ldqnx |
| 3 | 0x1226792000 |
libsecpol.so.1 |
20K | 4K | 库 | 紧邻 |
| 4 | 0x1226797000 |
**zero ELF** |
(0) | 4K | bss | ← libsecpol |
| 5 | 0x1226799000 |
libslog2.so.1 |
20K | 4K | 库 | 间隔 4K |
| 6 | 0x122679e000 |
**zero ELF** |
(0) | 4K | bss | ← libslog2 |
| 7 | 0x12267a0000 |
libcam.so.2 |
96K | 4K | 库 | 间隔 4K |
| 8 | 0x12267b8000 |
**zero ELF** |
(0) | 4K | bss | ← libcam |
| 9 | 0x12267ba000 |
libc.so.6 |
668K | 8K | 库 | 间隔 4K |
| 10 | 0x1226861000 |
**zero ELF** |
(0) | 16K | bss | ← libc ① |
| 11 | 0x1226867000 |
**zero ELF** |
(0) | 24K | bss | ← libc ② |
| 12 | 0x122686d000 |
libgcc_s.so.1 |
112K | 4K | 库 | 紧邻 |
| 13 | 0x1226889000 |
**zero ELF** |
(0) | 4K | bss | ← libgcc |
| 14 | 0x122688b000 |
io-blk.so |
288K | 12K | 库 | 间隔 4K |
| 15 | 0x12268d3000 |
**zero ELF** |
(0) | 8K | bss | ← io-blk |
| 16 | 0x12268d8000 |
libfsnotify.so.1 |
40K | 12K | 库 | 间隔 12K |
| 17 | 0x12268e2000 |
**zero ELF** |
(0) | 4K | bss | ← libfsnotify |
| 18 | 0x12268e6000 |
pci_bkwd_compat.so.3.0 |
16K | 4K | 库 | 间隔 12K |
| 19 | 0x12268ea000 |
**zero ELF** |
(0) | 4K | bss | ← pci_bkwd_compat |
| 20 | 0x12268ec000 |
libpci.so.3.0 |
136K | 16K | 库 | 间隔 4K |
| 21 | 0x122690e000 |
**zero ELF** |
(0) | 8K | bss | ← libpci |
| 22 | 0x1226914000 |
pci_slog2.so.3.0 |
8K | 4K | 库 | 间隔 16K |
| 23 | 0x1226916000 |
**zero ELF** |
(0) | 4K | bss | ← pci_slog2 |
| 24 | 0x1226918000 |
pci_hw-Intel_x86.so.3.1 |
104K | 4K | 库 | 间隔 4K |
| 25 | 0x1226932000 |
**zero ELF** |
(0) | 4K | bss | ← pci_hw ① |
| 26 | 0x1226934000 |
**zero ELF** |
(0) | 64K | bss | ← pci_hw ② |
| 27 | 0x1226944000 |
cam-disk.so |
12K | 4K | 库 | 紧邻 |
| 28 | 0x1226947000 |
**zero ELF** |
(0) | 4K | bss | ← cam-disk |
| 29 | 0x1226949000 |
fs-qnx6.so |
224K | 4K | 库 | 间隔 4K |
| 30 | 0x1226981000 |
**zero ELF** |
(0) | 4K | bss | ← fs-qnx6 |
| 31 | 0x2afa750000 |
/dev/shmem/slogger2/devb_eide.53254..0 |
(0) | 68K | shmem | 簇② |
| 32 | 0x2afa761000 |
/dev/shmem/slogger2/devb_eide.53254..1 |
(0) | 68K | shmem | 紧邻 |
| 33 | 0x2afa772000 |
/dev/shmem/pci/pci_db |
(0) | 36K | shmem | 紧邻 |
| 34 | 0x2afa77b000 |
/dev/shmem/pci/pci_sync |
(0) | 4K | shmem | 紧邻 |
| 35 | 0x2afa77c000 |
/dev/shmem/pci/pci_hw |
(0) | 4K | shmem | 紧邻 |
| 36 | 0x2afa77d000 |
**anonymous** |
(0) | 4K | anon | 紧邻 |
| 37 | 0x2afa77e000 |
sysram&below4G |
(0) | 4K | 物理内存 | 紧邻 |
| 38 | 0x2afa77f000 |
sysram&below4G |
(0) | 4K | 物理内存 | 紧邻 |
| 39 | 0x2afa780000 |
**anonymous** |
(0) | 64M | anon | 紧邻 |
| 40 | 0x2afe790000 |
sysram&below4G |
(0) | 4K | 物理内存 | 间隔 64K → 簇③ |
| 41 | 0x3072480000 |
**heap** |
(0) | 44K | 堆 | 簇④ |
| 42 | 0x307248b000 |
**heap** |
(0) | 4K | 堆 | 紧邻 |
| 43 | 0x307248c000 |
**heap** |
(0) | 2616K | 堆 | 紧邻 |
| 44 | 0x307271b000 |
**heap** |
(0) | 244K | 堆 | 间隔 4K → 簇⑤ |
| 45 | 0x3072759000 |
**heap** |
(0) | 92K | 堆 | 间隔 4K |
| 46 | 0x3072774000 |
**heap** |
(3000) | 204K | 堆 | 间隔 16K |
| 47 | 0x4ada4c5000 |
devb-eide |
116K | 12K | 本体 | 簇⑥,孤立 |
后续的进程分析类似,本篇就不继续分析了。
3 总结
本篇介绍了QNX系统中pidin mem指令输出中进程数据的内存分析。
127