虚拟地址空间
理论上,虚拟地址空间的大小取决于CPU的位数。32位的CPU最大虚拟地址空间为322-1,指针大小的位数与虚拟空间的位数相同。32位为4字节,64位为8字节。 虚拟空间由操作系统掌控,并不是整个虚拟空间都能归进程自由访问。
装载
指令和数据需要被装载进内存(物理内存)才能够被执行。进程所需的内存往往大于物理内存的数量,需要动态装载的机制。
1. 覆盖装入
程序被分割为小的模块,使用额外的辅助程序来管理模块的加载,模块的依赖关系呈现树型结构。
2. 页映射
内存和磁盘上的指令和数据块分为相同大小的页,以页为最小单元来装载。
进程的建立
- 创建一个独立的虚拟空间。
- 读取可执行文件头,建立虚拟空间与可执行文件的映射关系。
- 将指令寄存器设置为可执行文件的入口地址,启动运行。
创建虚拟地址空间其实是建立一个页表,里面用来存放虚拟空间到物理内存空间的映射关系。
程序头表是ELF文件按照 Segment 划分后,各个Segment的属性信息。 目标文件,不会被加载,所以没有程序头表
Elf file type is EXEC (Executable file)
Entry point 0x8048736
There are 6 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0xa11c1 0xa11c1 R E 0x1000
LOAD 0x0a1f5c 0x080eaf5c 0x080eaf5c 0x01024 0x01e48 RW 0x1000
NOTE 0x0000f4 0x080480f4 0x080480f4 0x00044 0x00044 R 0x4
TLS 0x0a1f5c 0x080eaf5c 0x080eaf5c 0x00010 0x00028 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
GNU_RELRO 0x0a1f5c 0x080eaf5c 0x080eaf5c 0x000a4 0x000a4 R 0x1
进程虚拟空间的分布
Section 和 Segment
在链接的角度,ELF文件是按 Section 来存储的,在装载的角度,ELF是按 Segment 来划分的。 如果以 Section 为最小单元来划分为若干页来加载,那么会出现很多的页内部碎片。若干个 Section 可以合并为一个 Segment 来分页(相同权限、属性)。
查看进程虚拟空间
08048000-080ea000 r-xp 00000000 08:01 3149407 /home/apollo/Desktop/source.elf
080ea000-080ec000 rw-p 000a1000 08:01 3149407 /home/apollo/Desktop/source.elf
080ec000-080ed000 rw-p 00000000 00:00 0
082fa000-0831c000 rw-p 00000000 00:00 0 [heap]
b7fe8000-b7feb000 r--p 00000000 00:00 0 [vvar]
b7feb000-b7fed000 r-xp 00000000 00:00 0 [vdso]
bf9a8000-bf9c9000 rw-p 00000000 00:00 0 [stack]