参考:《程序员的自我修养》
程序执行时,所需要的指令和数据必须在内存中才能正常运行。
但是,往往程序所需要的内存大于物理内存,无法把所有指令和数据全部放在内存中。
通过增加内存来解决这个问题,不太划算,因为相对于内存而言,磁盘比较便宜,因此动态装载就出现了。
分页:把地址空间人为地分为固定大小的页,每一页的大小由硬件或操作系统决定。对于系统而言,页的大小是固定的。
为什么可执行文件常常被叫做image?
可执行文件在装载时,实际上是被映射的虚拟空间。
1. 进程虚拟地址空间
虚拟地址空间由计算机硬件平台决定。硬件平台决定了地址空间的最大上限,即硬件寻址空间大小。
- 32位的硬件平台,虚拟地址空间的范围为 0 ~ 232,即0x00000000 ~ 0xFFFFFFFF。4GB。
- 64位的硬件平台,虚拟地址空间的范围为 0 ~ 263,即0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF。
C语言中,指针大小的位数与虚拟空间位数相同。32位平台的指针为32位,4个字节;64位平台的指针为64位,8个字节。
通常将虚拟地址空间分为两部分:系统虚拟地址空间和用户虚拟地址空间。用户进程只能访问用户虚拟地址空间,若访问了系统地址空间,便会报错。常见错误为:“Segmentation fault”(Linux),“进程因非法操作需要关闭”(Windows)。
- Linux默认分配:系统1GB,地址范围 0xC0000000 ~ 0xFFFFFFFF;用户3GB,地址范围0x00000000 ~ 0xBFFFFFFF。
- Windows默认分配:系统2GB,用户2GB。可更改。
2. 装载
进程的建立,需要做3件事:
- 创建独立的虚拟地址空间;
- 读取可执行文件头,建立虚拟空间与可执行文件的映射关系;
- 将CPU指令寄存器设置成可执行文件的入口地址,启动运行。
页映射关系函数:虚拟空间到物理内存的映射关系。
虚拟空间与可执行文件的映射关系:当程序执行发生页错误时,操作系统将从物理内存中分配一个物理页,然后将该“缺页”从磁盘读取到内存中,再设置“缺页”的虚拟页和物理页的映射关系。
- 可执行文件被映射时,以页长度作为单位。
3. 可执行文件链接视图和执行视图
ELF文件段的权限组合情况:
- 可读可执行:代码段
- 可读可写:数据段、BSS段
- 只读:只读数据段
为了节省内存空间,可执行文件在虚拟内存映射时,可以采取的方案:对于相同权限的段,合并到一起当作一个段进行映射。
Section:从存储的角度。链接视图。
- readelf -S file.elf 可以查看可执行文件的Section信息。
Segment:从装载的角度。执行视图。
- readelf -l file.elf 可以查看可执行文件的Segment信息。