1、链接(linking)是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可以被加载(或被拷贝)到存储器并执行。链接可以执行于编译时(compile time),即源代码被编译成汇编代码时,对应静态链接;也可以执行于加载时(load time ),通过命令行加载,程序被加载器加载到存储器中并执行时,对应动态链接;或执行于运行时(run time),通过在代码中使用接口dlopen,由应用程序来执行,对应动态链)。
2、目标文件的三种形式:1)可重定位目标文件,包含二进制代码和数据,可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件;2)可执行目标文件,包含二进制代码和数据,可以被直接加载到存储器并执行;3)共享目标文件,一种特殊类型的可重定位目标文件,可以在加载或者运行时被动态地加载到存储器并链接。 注意:虚拟存储器简化了加载,加载器从不实际拷贝任何数据从磁盘到存储器,而是在每个页被引用时,按需页面调度。(P541)
可执行目标文件包含的几个重要的节:1).text:已编译程序的机器代码;2).data:已初始化的全局C变量或static变量;3).bss:未初始化的全局C变量或static变量。
3、静态编译:以一组可重定位目标文件作为输入,生成一个完全链接的可以加载和运行的可执行目标文件作为输出。静态库编译:将所有相关的目标模块打包成为一个单独的文件,当链接器 构造一个输出的可执行文件时,它只拷贝静态库里被应用程序引用的目标模块。见下图:
链接器必须完成的两个任务:1)符号解析(symbol resolution),将每个符号引用刚好和一个符号定义联系起来;2)重定位(relocation),把每个符号定义与一个存储器位置(虚拟地址空间)联系起来,然后修改所有对这些符号的引用,是的它们指向存储器位置,从而重定位这些节。
4、动态链接共享库:共享库是一个目标模块,在运行时,可以加载到任意的存储器地址,并和一个在存储器中的程序链接起来。Unix系统中用.so后缀来表示动态库,windows里成为DLL。见图3。
共享方式:1)在任何给定的文件系统中,对于一个库只有一个.so文件,所有引用该库的可执行目标文件共享这个.so文件中的代码和数据,而不是像静态库的内容那样被拷贝和嵌入到引用它们的可执行的文件中;2)在存储器中,一个共享库的.text节的一个副本可以被不同的正在运行的进程共享。
注意:部分链接的可执行目标文件不包含libvector.so的代码和数据节,反之链接器只拷贝了一些重定位和符号表信息,它们使得运行时可以解析对libvector.so中的代码和数据的引用。
动态链接器执行的任务:1)重定位libc.so的文本和数据某个存储器段(虚拟地址空间);2)重定位libvector.so的文本和数据到另一个存储器段;3)重定位部分链接的可执行目标文件中所有对libc.so和libvector.so定义的符号的引用。完成这三个任务后,共享库的位置就固定了,并且在程序执行的过程中都不会改变。
5、在应用程序中加载和链接共享库:Unix中使用dlopen接口,windows中使用动态库的方法参见:http://blog.csdn.net/microsues/article/details/6059912