15:58 2020/1/15
#操作系统 ##OS
1.进程和线程
1\进程是资源分配的最小单位,线程是程序执行的最少单位(资源调度的最少单位)
2\进程有自己的独立地址空间,每启动一个进程,系统就会为其分配地址空间,建立数据表来保护代码段、堆栈段和数据段
线程是共享进程中的数据,同一进程下的不同线程使用共同的地址空间
3\线程间的通信方便,同一进程下的线程共享全局变量、静态变量等数据
进程间的通信需要通过IPC进行
2.电表中的进程和线程(zx操作系统中)
每一个任务为一个进程,由操作系统来为其创建进程(读取app.bin,创建一个进程)
平时在编写的为线程,同一工程下的,不同线程可以访问同一内存
Keil在设置时(数据无关实现,ROPI/RWPI):
"Options -> C/C++"选项卡:
Read-Only Position Independent 为RO常量生成独立的代码空间
Read-Write Position Independent 为RW全局变量生成独立的代码空间
"Options -> Asm"选项卡:
Read-Only Position Independent 为RO常量生成独立的代码空间
Read-Write Position Independent 为RW全局变量生成独立的代码空间
"Options -> Linker"选项卡:
Make RW Sections Position Independent RW段运行时可更改
Make RO Sections Position Independent RO段运行时可更改
动态加载的原理:
编译的时候会为每一个全局变量生成一个相对于r9寄存器的偏移量,这个偏移量会在.text段
操作系统加载elf文件时:ropi/rwpi处理
a\rwpi:将RW段加载到RAM中后,将R9寄存器指向此片内存的基地址
b\ropi:在编译期间,通过PC的相对偏移来表示符号的地址(函数调用/只读变量的访问)
且每个函数的代码最后会有一个临时的RO-Data表,存放函数内要调用符号的地址(类似plt和got)
可以理解为:编译链接时,用PC=0编译,得到相对位置,运行时,带入实际PC得到最终的实际位置
所以:
对于RO和CODE:
当不使用\ropi\时,编译器和链接器会直接使用符号的绝对地址
使用\ropi\,则通过PC的偏移来表示(RO/CODE都是一整块下载的,块内是连续的)
基址寄存使用的PC寄存器(所以不能跨模块调用,即不能实现动态链接,动态加载仍是静态链接)
对于RW(DATA,ZI本质也是RW,只是在初始赋值时的操作不一样,当运行起来的地址都是唯一确定的,所以统称RW):
RW需要被加载到RAM中,加载时连同ZI一起(ZI通过调用初始赋值函数初始化,同样/ropi/)
实际上,加载器只需要创建一个进程,然后以此进行以下操作:
1).加载程序bin文件的起始地址,即入口地址
2).分配RAM空间,将此RAM的基地址赋给r9寄存器
3).startup此进程,由此进程自己将RW初始化好
示例(/rwpi/):
elf_test_num = 2;//赋值语句,其中:elf_test_num为全局变量
1\无动态加载时:
MOVS r0, #2
LDR r1, #&elf_test_num ;&elf_test_num为伪代码,表示变量elf_test_num的地址
STR r0, [r1] ;[elf_test_num] = 2
2\有动态加载时:
MOVS r0, #2
LDR r1, #16 ;这里使用一个虚拟的RW区,实际不存在,这里只是获取一个相对偏移
ADD r1, r1, r9 ;r9存放的真正的RW区的基地址,操作系统在加载RW到内存时设置r9的值,&elf_test_num == (r9 + 16)
STR r0, [r1] ;[elf_test_num] = 2
3.操作系统在加载程序时需要获取的信息
1\RW段的大小
2\程序的入口地址
4.zx操作系统lwp支持
1\生成.bin文件
a\经过/rwpi/和/ropi/的相关配置,keil编译链接的代码中RO和RW段独立,且与地址无关
b\Rebuild后,生成.axf文件,此文件包含.bin信息,以及调试信息
c\通过命令:"fromelf --bin !L --output app.bin",提取出.bin信息(可直接下载)
--bin 表示要生成bin文件
!L 为.axf文件的路径+axf文件名称,如"D:\1\out\app.axf"
--output xxx 指定生成的文件的文件名
2\修改bin文件中的名称
通过命令"../sdk/tools/packtool.exe -f ./app.bin -n uart",名称被修改为"uart"(不是.bin文件的文件名)
只是单纯的修改.bin文件中的名称字段(.bin文件的格式未知)
5.动态加载的文件分析
Keil编译链接后程序和数据空间大小:
Program Size: Code=189272 RO-data=22156 RW-data=7336 ZI-data=86052
只读RO:Code + RO-Data = 189272 + 22156 = 211428(=0x339E4)
读写RW:ZI-data + RW-data = 86052 + 7336 = 93388(=0x16CCC)
RO + RW = 211428 + 93388 = 304816(=0x4A6B0)
ZI-Data存放在.bss段中
分析.axf文件(ELF格式)
程序头部表
.p_filesz = 211428 + 2028 = 213456(=0x341D0)(text + data = Code + RO-Data + data)
.p_memsz = 304816(=0x4A6B0)(RO+RW)
1\Program-Header程序头0(只有节头,没有对应的节)
p_offset程序节的偏移
-----------
01 00 00 00 (34 00 00 00)00 00 00 00 00 00 00 00
(d0 41 03 00)(b0 a6 04 00)07 00 00 b0 08 00 00 00
----------- -----------
p_filesz p_memsz
2\Section-Header节头0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
3\Section-Header节头1(.text节)
01 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00
(34 00 00 00)(e4 39 03 00)00 00 00 00 00 00 00 00
----------- -----------
sh_offset sh_size=211428=RO=Code+RO-Data
04 00 00 00 00 00 00 00
3\Section-Header节头2(.permission_table节)
06 00 00 00 01 00 00 00 02 00 00 00 e4 39 03 00
(18 3a 03 00)(00 00 00 00)00 00 00 00 00 00 00 00
----------- -----------
sh_offset sh_size=0
04 00 00 00 00 00 00 00
注意:大小为0!
4\Section-Header节头3(.data节)
18 00 00 00 01 00 00 00 03 00 00 00 e4 39 03 00
(18 3a 03 00)(ec 07 00 00)00 00 00 00 00 00 00 00
----------- -----------
sh_offset sh_size=2028=RW-Data(如果启动了"RW data compression",这个值不是RW-Data的实际大小)
04 00 00 00 00 00 00 00
5\Section-Header节头4(.bss节)
1d 00 00 00 08 00 00 00 03 00 00 00 8c 56 03 00
(04 42 03 00)(24 50 01 00)00 00 00 00 00 00 00 00
----------- -----------
sh_offset sh_size=86052-ZI-data
08 00 00 00 00 00 00 00
注意:
a\上一个节的sh_offset+sh_size=下一个节的sh_offset
b\.bss节实际并不存在(在ELF文件中只有节头表,没有实际对应的节空间)
c\从axf生成的bin文件,只包含:.text/.promissions_table/.data/.bss
其中:.promissions_table和.bss大小为0,故实际不存在,仅逻辑上存在
.text
.data
d\对比发现,.data段的大小只有2028字节,并非7336字节(但.text段中指明data最终大小的用的7336)
原因是:Keil的"RW data compression"功能
RW data areas typically contain a large number of repeated values,
such as zeros, that makes them suitable for compression.
RW data compression is enabled by default to minimize ROM size.(默认开启)
The linker compresses the data. This data is then decompressed on the target at run time.(运行时解压缩,类似ZI的实现,但不算做ZI的数据)
实现方式:
Keil通过代码来对RW数据进行压缩(方式和ZI的初始化流程一致,但本质不一样)
ZI初始化可能默认用0初始化,RW压缩可能用重复值进行压缩。
作用:
减少ELF文件的大小,无论是否压缩,最终运行时的.data空间是一样的
Keil中的.map文件解析:
Code inc. data RO Data RW Data ZI Data Debug
189272 9256 22156 7336 86052 1000928 Grand Totals
189272 9256 22156 2028 86052 1000928 ELF Image Totals (compressed)
注意:内联数据(inc.data),例如文字池和短字符串,无需关心(包含在RO Data中)
6\Section节0(.text节)以下列举前128字节
1f 49 1f a2 11 44 08 47 | 这里实际是命令了(反汇编查看,Reset_Handler函数)
| 491f ADR r1,[pc,#124] ;取[pc+128]处的值,这里的值是相对[pc+128]的偏移,是相对的
| a21f ADR r2,{pc}+0x80 ;获取[pc+128]处对应的地址,{PC}是隐含的
| 4411 ADD r1,r1,r2 ;得到运行时(被加载后)的绝对地址
| 4708 BX r1 ;跳转(通过反汇编查看,这里跳转到__main函数)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
(4c 57 50 2e)(cc 6c 01 00)(e4 39 03 00)(e4 39 03 00)
----------- ----------- ----------- -----------
=ASCII(LWP.) =93388 =211428 =211428
=RW =RO =data段的相对偏移(推测,实际含义未知)
>分配RAM空间
61 70 70 00 00 00 00 00 00 00 00 00 00 00 00 00 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 存放名称(可修改,zx以此作为应用名称,目前测试发现最大支持长度为32)
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...
注意:Reset_Handler函数的实现方式是sdk.lib提供的,是和最终运行的操作系统搭配的
在操作系统(zx)提供的应用层调用库sdk.lob中可以找到相同的数据段(上述的数据段)
6.总结
zx操作系统的lwp实现过程
1\操作系统会识别加载的app.bin文件的指定位置(文件起始Reset_Handler函数后的数据区),读取RW大小和data段的偏移
操作系统识别后,给data段分配RAM空间,创建指定的进程,同时将RAM的起始地址赋给r9,调度程序运行
2\操作系统给应用层程序提供.lib库,除了包含操作系统接口外,还涉及一些配置
如:提供.o文件(需要应用层的工程在分散加载链接时使用)
zx提供的sdk.lib文件中的startup.o中的RESET节,需要在sct文件中指定,链接时放置在.text段的最开始
RESET节中包含了操作系统识别的必要信息
3\编译链接
启用PI(地址无关)后,编译器的编译策略改变,引入/rwpi/和/ropi/的编译策略
在符号调用处使用相对偏移
a\对于函数调用,处理为在本函数后面紧跟符号地址表(外部符号,内部符号无特殊处理)
链接器在链接期间会修改这个地址表,根据这个地址表计算相对偏移,所以编译器需要对代码做如下处理
1).对外部符号的调用,编译器处理成先获取地址表的值,再加上地址表的实际地址
2).连接完成后,给定一个程序启动地址(程序文件运行时的地址),唯一的确定一组符号地址关系
b\对于全局变量,处理为:r9+相对RW起始的偏移
这个相对偏移,同样存储再函数后面的地址表中
来源:CSDN
作者:DENGCHOW
链接:https://blog.csdn.net/weixin_39869569/article/details/104041494