编译过程
预处理
宏展开,略
编译
词法分析,语法分析,语义分析,中间代码生成,
目标代码生成
这一步是将中间代码编程汇编代码,这个过程中会把符号换成地址,如果是外部的符号,则留下符号作为占位符,等以后再链接修改
汇编
把汇编码转为机器指令
静态链接
有个重定位关系
ELF结构
首先讲一下我们的程序,这里讲elf结构
Elf文件格式可以有:
- 已初始化全局变量和静态变量data,
- 未初始化全局变量bss,
- 只读数据/编译器常量rodata,
- 机器码text等Section。
- 符号表,重定位信息等略
另外全局变量可能在数据段或者bss
static静态变量,如果修饰局部变量,和全局变量放在同一个区域,可以把它看成是作用域为那个局部的全局变量,同理类成员
未初始化区域bss为什么要和全局变量分开来装,猜也猜得到因为省空间
字符串常量,字面值都是放在rodata,比如cpp的虚表就是放在这里的,运行时期修改会有segmentation fault
程序加载运行时,.rodata段和.text段通常合并到一个Segment中,操作系统将这个Segment的页面只读保护起来,防止意外的改写。这一点从readelf的输出也可以看出来
启动过程
整个装载的过程
首先操作系统会读取可执行文件的头部,检查文件的合法性,然后从头部中的“Program Header”(这个program header是什么)中读取每个“Segment”的虚拟地址、文件地址和属性(这里说的segment是内存五区之类的吧),并将它们映射到进程虚拟空间的相应位置,接着操作系统就会把控制权交给可执行文件的入口地址,然后程序开始执行。
ELF文件装载过程
读取一个程序,首先要创建个进程,在bash输入一个文件,首先bash会负责调用这个fork函数,因为有写时复制机制,创建的task_struct只是单纯的复制了bash的task_struct的mm位,并调用execv()函数来读取这个a.out文件,
然后就是execv的过程,首先会读取这个文件的开头位置,来判断这个文件的类型,从而调用相应的函数来处理
如ELF的文件会调用load_el_binaryf函数来处理,以下是它的过程
首先会读取header(和上面的读取开头不是一样的吗),用来检测ELF的有效性(用类似checksum来保证有效性吗?),并读取program header table,里面包含了内存分段的信息,于是把相应的文件映射到相应的内存片段里(更多TODO),
然后是动态链接过程(静态链接已经在编译阶段完成了),---
操作系统会启动一个动态链接器——ld.so,它其实是个共享对象(说的是这个程序吧),加载完动态链接器之后,将控制权交给动态链接器的入口地址。
动态链接器开始执行一系列自身的初始化操作,然后根据当前的环境参数,开始对可执行文件进行动态链接工作(没说怎么动态链接的呀)
所有动态链接工作完成后,动态链接器就会将控制权交给可执行文件的入口地址(参考资料4提到这一步对于内核来说很复杂),程序开始正式执行。
参考资料
- https://blog.youkuaiyun.com/niu15273122295/article/details/80236985
- https://juejin.im/post/6844904004632182791可执行文件的装载
- https://juejin.im/post/6844904016124608519整个运行过程,这篇内容很多还得慢慢消化
- https://www.cnblogs.com/fr-ruiyang/p/11196858.html这个提到很多概念都看不懂.比如跳转到函数开头,说是把CPU控制权给进程
变量和常量参考
- https://www.zhihu.com/question/35782789为什么区分变量和常量
- https://www.zhihu.com/question/418999081为什么cpp要区分变量常量
- C++的进程中的数据段、代码段、系统栈、PCB 分别在操作系统内存的什么地方https://www.zhihu.com/question/57476183/answer/153045281
- ELF详解https://blog.youkuaiyun.com/daide2012/article/details/73065204
- https://blog.youkuaiyun.com/yangcunbiao/article/details/83020443字符串常量摆放区域
- https://www.bookstack.cn/read/linux-c/747bb4f6770d0dbf.md?wd=%E5%86%99%E7%BB%99字面值,挺全的网站
TODO
- python的运行过程,编译和装载放在一起的吗?
- 动态链接的完整过程 https://www.zhihu.com/question/28469080/answer/747953080这里说的好细啊
- https://www.nosuchfield.com/2018/11/23/Program-compilation-linking-loading-and-running/