为什么需要链接
在实际开发中,我们一定是多文件编程,所有文件在编译后,需要合在一起,合在一起的过程就是链接的过程。
每一个源文件(就是.c文件,上图中的程序1)都有对应的零碎文件(就是.h文件),通过预编译(通过#include实现)把.c和.h文件整合成一个组合C文件,这个组合C文件的扩展名为.i。把组合C文件编译成汇编文件.s,目标文件为机器指令(放在一个.o文件当中),单个目标文件是不能工作的,因为各个目标文件是相互支撑工作的。
把各个目标文件整合的过程就叫链接过程。整合后的文件就叫可执行程序,windows后缀为.exe,Linux后缀为.out
链接过程都干了什么事
目标文件主要分为两个区域:数据区域和指令区域。 每一个指令和数据都被安排了地址。
(1)地址重定位: 目标文件被整合的时候,每个目标文件的数据区被整合到一起,每个目标文件的指令区被整合到一起。假如目标文件1被整合前指令的地址是00000001,目标文件n整合前指令的地址也是00000001,整合到一起后,他们的地址是要重新编排的,这个叫地址重定位。数据区域的地址相应的也要重新编排。
重定位地址的作用:CPU会通过这个重定位的地址进行寻址,找到在内存中要执行的指令和数据,然后取出指令执行,并按照指令要求处理数据。重定位以后,会给执行文件中的计算机指令数据,重新安排地址,CPU会通过这些地址取指令执行,并处理这些数据。最终需要通过这些地址找到内存中的指令和数据。
链接脚本:重定位时,这个重定位的地址是如何安排的呢,需要使用一个链接脚本文件,这个文件中会有重定位地址的说明,重定位时,会按照这个脚本的重定位地址的要求,来进行地址重定位工作。
(2) 符号统一 : 直接举个C语言中的例子,假设程序有两个.c文件,分别是a.c和b.c,这两个文件中都有名叫var的变量,a.c被编译得到a.o,b.c被编译得到b.o,将a.o和b.o链接到同一个文件时,var命名重复了,需要根据规则对着两个符号进行统一,与此相似的还有函数名的“符号统一”问题。