目录
采用ELF格式的文件
ELF结构
可执行程序的加载
采用ELF格式的文件
可重定位文件(Relocatable File):即xxx.o 文件。包含适合于与其他目标文件链接来创 建可执行文件或者共享目标文件的代码和数据。
可执行文件(Executable File):即可执行程序。
共享目标文件(Shared Object File):即 xxx.so文件。
内核转储(core dumps):存放当前进程的执行上下文,用于dump信号触发。
ELF结构
ELF头(ELF header):用于定位文件的其他部分。
程序头表(Program header table):记录有效段(segment)和他们的属性。包括开始的位置,位移,长度。
节头表(Section header table):记录节(section)的属性。节(Section):记录各种数据,比如可执行代码,全局变量等。
ELF格式同时服务于两个完全不同的阶段(链接阶段+执行阶段),所以故意设计成两种视图。
从源代码到可执行程序的过程是这样的。
1.将源代码编译成.o文件,由编译器完成。
2.将.o文件和库链接,由链接器完成。这个过程通过ELF文件的链接视图将拥有相同属性的节合并(不绝对)成segment段。具体合并原则被记录在 了 ELF 的 程序头表(Program header table) 中。
3.内核根据 program header table 装载运行。
可执行程序的加载
创建一个进程,先创建内核中进程相关的数据结构,再加载ELF格式的二进制文件。
编译器只产生相对偏移 + 重定位需求;链接器才真正分配虚拟地址,并把它们固定(或相对固定)写进最终的 ELF 文件中。
可执行程序从磁盘上加载到物理内存中,每行代码都有自己的虚拟地址(ELF)和物理地址(物理内存)。没有加载就只有虚拟地址(ELF)。
cpu从哪开始执行?ELF的head中有一个Entry point address对应的是代码段的开始,cpu从此开始执行。cpu读到某个需要跳转的函数的虚拟地址后,将虚拟地址给MMU,MMU通过寄存器CR3查页表,就拿到了物理地址,便可以读取相应的内容。所以进cpu的都是虚拟地址,出来的是物理地址。
用户写源代码,编译器编译,这个过程会产生相对偏移的,编译完成有了ELF格式,链接器链接,链接完成有了真正的虚拟地址,形成可执行程序。ELF包括了某些权限相同的节组成的段还有什么代码段的开始(将来给cpu的)。此刻可执行程序在磁盘中。可执行程序要加载,先通过加载器到虚拟地址空间,填页表,按需分配物理内存,建立起映射关系,其中那个ELF程序头表就是给加载器看的吧。之后通过内核调度,给cpu第一条虚拟地址,通过页表的映射关系,找到物理地址进行读写。如果物理地址没有数据触发缺页中断,内核再次到磁盘读写数据到物理内存。碰到函数的调度,就需要将虚拟地址给MMU,MMU通过CR3查页表,转换成物理地址再次读写。
一张浅浅的流程图