进程虚拟地址空间
操作系统管理所有硬件,程序在运行时也是由操作系统通过虚拟地址空间的映射去管理。这样就避免了直接使用物理地址,避免他人能够直接通过物理地址对主机进行恶意程序调用。如果想调用物理硬件就需要用到编程接口(系统调用)。
在操作系统中,对每一个进程应用都是分配的4GB的虚拟内存。在32位4GB的内存中,操作系统会用1GB来存储操作系统的代码,剩余3GB给用户,操作系统的1GB是给所有进程共享的。虚拟内存mmap段中的动态链接库仅在物理内存中装载一份。(windows:2GB给用户,2GB给内核)
段(segment)与节(section)
段视图用于进程的内存区域的rwx权限划分,节视图用于ELF文件编译链接时与在磁盘上存储时的文件结构的组织。一个段包含了多个节。
- 代码段(Text segment)包含了代码与只读数据
- .text节
- .rodata节(read only data)
- .hash节
- .dynsym节
- .dynstr节
- .plt节(解析动态函数的实际地址)
- .rel.got节
- .......
- 数据段(Data segment)包含了可读可写数据
- .data节(声明了的全局变量)
- .dynamic节
- .got节
- .got.plt节
- .bss节(还未声明的全局变量)
- ......
- 栈段(Stack segment)
大端序和小端序
- 小端序:低位存放低地址、高位存放高地址
- 大端序:低位存放高地址、高位存放低地址
程序的装载与进程的执行
amd64寄存器结构
- rax:8 Bytes
- eax:4 Bytes
- ax: 2 Bytes
- ah: 1 Bytes
- al: 1 Bytes
部分寄存器的功能
- RIP:存放当前执行的指令的地址
- RSP:存放当前栈帧的栈顶地址
- RBP:存放当前栈帧的栈底地址
- RAX:通用寄存器。存放函数返回值
静态链接的程序的执行过程
- 运行一个binary程序,然后通过调用fork这个函数去复制一份虚拟内存,逐层的通过用户级函数申请调用,到内核级函数开始运行,准备好内存之后,开始准备环境。最后执行代码。
动态链接的程序的执行过程
- 它在准备好内存之后,需要通过链接器(ld.so)先其他动态链接库获取代码。