#静态链接
从一开始学习C++或者java就是用IDE去开发,在IDE中基本只需要编写代码,然后按个编译运行按钮就可以了。所以在刚学的时候根本就没有理解好整个编译链接的过程。
昨晚大致看了该书的第二部分,静态链接。其实静态链接与动态链接的本质不同就在与一个是在生成可执行文件的时候就已经将文件链接起来,一个可以动态地装载卸载。
我们使用的IDE build程序,实际上包含了很多个步骤:
- 预编译
- 编译
- 汇编
- 链接
预编译
预编译的命令如下:
gcc -E hello.c -o hello.i
或者是
cpp hello.c > hello.i
预编译主要就是处理以#开头的预编译指令,比如#include ,#program 等等
在预编译中会将宏展开,在预编译的结果中是没有宏的,并且包含的头文件也被嵌入到.i文件中,如果我们想要判断宏定义以及头文件包含是否正确,我们可以使用预编译来判断。
编译
编译就是将预编译得到的文件进行我们经常说的词法分析、语法分析、语义分析以及优化后生成相应地汇编代码文件,这个过程就是平常说的程序构建最核心的部分,也是最复杂的部分。
使用如下命令即可完成汇编:
gcc -S hello.c -o hello.s
汇编
汇编器就是将汇编代码汇编成机器可执行的指令,每一条汇编语句几乎对应着一条机器指令。我们可以用汇编器as来完成汇编
as hello.s -o hello.o
或者
gcc -c hello.s -o hello.o
链接
如果写过一点点c/c++小工程的都知道,那些程序源文件都是有很多个的,这样编译后是会有很多个目标文件的。而链接就是将各个输出目标文件连起来,组成一个可执行文件。
目标文件
在编译后,我们会得到一些文件,这些文件介于源文件与可执行文件之间,这个叫目标文件。目标文件从结构上来讲,它已经是编译后的可执行文件,只是还没有经过链接。
另外不光是可执行文件按照可执行文件的格式存储,动态链接库跟静态链接库都是可以按照可执行文件格式存储的,它们在Windows下按照PE-COFF格式存储,在linux下面按照ELF格式存储。
而目标文件格式将文件的内容主要分成数据段,代码段,堆栈段,BBS段等。另外有一个链接密切相关表,符号表,它是链接器的接口。各个文件有相互引用,而链接器必须将这些文件链接在一起,所以每个文件都会有一个符号表,记录文件中使用的符号,比如函数符号。
链接器在对目标文件进行链接的时候,必须对文件中得有些部位进行重定位,而这个就需要重定位表了。
静态链接
静态链接其实就是将编译汇编后的文件,链接成一个可执行文件。在此过程中,它首先将各个目标文件合并,由于每个目标文件都有数据段,代码段等,链接器将这些段合并在一起,让每个文件的相同段相邻。一旦段的位置确定,链接器就可以进行符号解析和重定向,链接器会对每个对其他文件有引用的都进行解析,对每个段中徐重定位指令和数据进行“修补”,让他们都指向正确地位置。
参考
- 《程序员的自我修改-链接、装载与库》