编译链接浅析

来源:互联网 发布:淘宝开店贷款 编辑:程序博客网 时间:2024/05/11 21:13

概括、通过对编译和链接的过程分析更加深刻的掌握程序运行的机制。

一、编译

工程中的多个源文件经过预处理、词法分析、语法分析、语义分析、汇编成多个中间目标文件。

二、静态链接

2.1、随着工程量的增加不太可能用一个c文件实现整个工程的功能,需要把工程分成很多个模块,再把模块分解成很多个功能函数,一些具有相近功能的函数被放到一个c文件中。这样一个工程中就可能含有很多个c文件,他们分别进行编译,所以就需要把这些分别编译所生成的中间目标文件进行链接生成可执行文件。较为简单的是静态链接。

2.1、中间目标文件的结构是段式的结构,一般有代码段,数据段,bss段等。中间目标文件的格式和可执行文件的格式几乎一样,只不过是中间目标文件中函数和全局变量的地址无法确定而已。

2.2、每个中间目标文件中的函数和全局变量的地址是无法确定的,所以在对应的代码段中的地址函数地址对应-4,变量地址是0,我们需要在链接时对他们进行重定位。

2.3、重定位函数和全局变量的地址需要两个步骤,第一步是确定整个工程中所有函数和全局变量的虚拟地址,这个步骤是通过计算整个程序中一共含有多少个段,每个段的大小,段对齐设置,以及函数和全局变量在段中的偏移来获得。(代码段和数据段等在特定的操作系统下被装载到的虚拟地址的起始地址是固定的)

2.4、在获得了所有的函数和全局变量的虚拟地址以后,就要对代码段中的地址进行重定位,这是根据重定位表来的,重定位表就是需要重定位的地址和符号(函数和全局变量)的虚拟地址的索引表,这样就可以实现地址的重定位。

三、动态链接

3.1、系统的库函数等模块被应用程序调用的几率非常之大,如果都采用静态链接的话,每个可执行文件都含有相应的库模块的一个副本,无论是存储时还是运行时都极大的浪费空间,而且如果库文件版本升级的话就需要对整个工程进行编译,这就需要采用动态链接的方式来解决此问题。

3.2、动态链接顾名思义就是在装载时再确定模块的地址,这种情况下,动态模块的地址是随机的可变的,因为应用程序可能需要链接多个动态链接库模块,而随机的动态链接的模块地址带来的问题就是动态链接模块在不同的进程中是不一样的(地址不一样),这样的话就无法实现动态链接库代码的共享,为了使动态链接库的代码和数据的访问不随其被装载的地址不同而不同就需要使用地址无关代码技术。

3.3、对于模块内部的函数调用和静态变量的访问是采用相对地址的方式来进行的,所以就不需要地址的重定位。

3.4、而对于模块间的函数调用和全局变量的访问是采用间接访问的方式来进行的,也就是说访问函数和全局变量的间接地址,而这个间接地址是不变的,间接地址里的值就是函数和全局变量的真正地址是可变的。