跳至主要內容

动态链接(Dynamic Linking)

西风逍遥游大约 2 分钟

动态链接(Dynamic Linking)

相对于静态链接,还存在一种在运行时动态加载库的方式,被称为动态链接。对于现代操作系统来说,动态链接是一种非常重要的方式,绝大多数关键的系统库都是以动态链接的方式提供的。

为什么要动态链接

静态链接的方式有一个很大的缺点,就是浪费空间。比如,如果一个程序需要调用两个库,而这两个库都需要调用同一个库,那么在静态链接的方式下,这个库就会被复制两份,程序体积也就相应的增大。相比于浪费磁盘空间,静态链接对内存空间的浪费则显得更难接受,对于关键的系统函数,如果每个程序都必须打包自己的版本,那么随着加载的进程数目增多,大量的内存将由此浪费掉。而动态链接的方式下,这个库只会存在一份副本,这可以被多个程序共享。

动态链接的方式还有一个好处,就是方便更新。如果一个库需要更新,那么只需要更新这个库的副本,而不需要更新所有的程序。这对于动辄几百兆的大型程序来说,是一个非常大的优势。插件式的程序也是如此,如果一个程序需要支持插件,那么它就必须以动态链接的方式加载插件,否则插件的更新将会非常麻烦。

动态链接的实现

地址无关代码

在静态链接的方式下,由于每个程序都有自己的地址空间,因此程序中的地址都是相对于程序自身的地址空间的,这种代码被称为位置相关代码。而在动态链接的方式下,由于多个程序共享同一个库,因此库中的地址必须是相对于库自身的地址空间的,这种代码被称为位置无关代码

一般来说,位置无关代码的生成要依赖编译器分析,将地址引用分为模块间引用和模块内引用。对于模块间引用,编译器会生成一个全局偏移表,用于存放引用的地址,而对于模块内引用,编译器会生成一个局部偏移表,用于存放引用的地址。在程序加载时,由于库的地址是未知的,因此这些偏移表中的地址都是未知的,只有在程序运行时,才能将这些地址填充完整。