深入理解计算机系统--链接
引言
链接是将各种代码和数据收集起来并组合成一个单一文件的过程,这个文件可被加载到存储器并执行。
现代系统中,链接是由链接器(linker)自动执行的。
符号解析
首先定义强符号与弱符号。
- 强符号:函数和已初始化的全局变量。
- 弱符号:未初始化的全局变量。
规则1
不允许有多个强符号。
规则2
如果有一个强符号和多个弱符号,那么选择强符号。
如果在一个模块里x未被初始化,那么链接器将安静地选择定义在另一个模块中的强符号。
规则3
如果有多个弱符号,那么从这些弱符号中任意选择一个。
一个有趣的错误
在foo5模块中,x被定义为int类型;在bar5模块,x被定义为double类型。
1 |
|
使用gcc(版本为4.8.0)编译,会有警告信息。与参考文献中所说的没有警告信息有出入。
1 |
|
运行结果:
1 |
|
结果显示,y的值被修改,这是因为double类型是8个字节,int类型是4个字节,在bar5模块中对x赋值,双精度浮点数覆盖了存储器中x和y的位置。
重定位
链接器完成符号解析之后,就可以把代码中的每个符号引用和确定的一个符号定义联系起来。此时,链接器就知道它的输入目标模块中的代码节和数据节的确切大小,就可以开始重定位了。
重定位由两步组成:
- 重定位节和符号定义。链接器将所有相同类型的节合并,得到新的聚合节。
- 重定位节中的符号定义。链接器修改代码节和数据节中对每个符号的引用,使他们指向正确的地址。
动态链接共享库
静态库的缺点
- 需要定期维护和更新,如果程序员想使用最新版本,必须了解该库的更新情况,显式地将程序与更新的库重新链接。
- 库中被调用函数的代码会被复制到每个运行进程的代码段中,几乎每个程序都会包含标准I/O函数,这对存储资源是一种浪费。
共享库是致力于解决静态库缺陷的一个现代创新产物。共享库是一个目标模块,在运行时可以加载到任意的存储器地址,并和一个在存储器的程序链接起来。这个过程称为动态链接,由动态链接器的程序来执行。
共享库也称为共享目标(shared object)。在Unix、Linux系统中通常用后缀.so来表示。Window系统也大量利用了共享库,称为动态链接库,用后缀.dll来表示。
参考文献
- (美)布莱恩特(Bryant, R. E.), (美)奥哈拉伦(O’Hallaron),等. 深入理解计算机系统[M]. 机械工业出版社, 2012.
深入理解计算机系统--链接
http://zhaoshuaijiang.com/2016/05/20/csapp-7-linking/