静态跟动态链接
静态和动态链接引言即使是最简单的HelloWorld的程序,它也要依赖于别人已经写好的成熟的软件库,这就是引出
静态和动态链接
引言即使是最简单的HelloWorld的程序,它也要依赖于别人已经写好的成熟的软件库,这就是引出了一个问题,我们写的代码怎么和别人写的库集成在一起,也就是链接所要解决的问题。
首先看HelloWorld这个例子:
linux-gate.so.1 => (0x008cd000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00a7a000) /lib/ld-linux.so.2 (0x0035d000)
都表明该可执行文件依赖于libc.so.6这个动态库,也就是C语言标准库的动态链接版本。如果某个库依赖于别的动态库,它们也会被加载进来直到所有依赖的库都被加载进来。
当所有的库都被加载进来以后,类似于静态链接,动态链接器从各个动态库中可以知道每个库都提供什么函数(符号表)和哪些函数引用需要重定位(重定位表),然后修正.got和.got.plt中的符号到正确的地址,完成之后就可以将控制权交给可执行文件的入口地址,从而开始执行我们编写的代码了。可见,动态链接器在程序运行前需要做大量的工作(修正符号地址),为了提高效率,一般采用的是延迟绑定,也就是只有用到某个函数才去修正.got.plt中地址,具体是如何做到延迟绑定的,推荐看《程序员的自我修养》一书。小结链接解决我们写的程序是如何和别的库组合在一起这个问题。每个参与链接的目标文件中都提供了这样的信息:我有什么符号(变量或者函数),我需要什么符号,这样链接器才能确定参与链接的目标文件和库是否能组合在一起。静态链接是在生成可执行文件的时候把需要的所有内容都包含在了可执行文件中,这导致的问题是可执行文件大,浪费磁盘和内存空间以及静态库升级的问题。动态链接是在程序运行的时候完成链接的,首先是动态链接器被加载到内存中,然后动态链接器再完成类似于静态链接器的所做的事情。