linux环境下动态链接和静态链接

一个程序要想在内存中运行,除了编译之外还要经过链接和装入这两个步骤。从程序员的角度来看,引入这两个步骤带来的好处就是可以直接在程序中使用printf和errno这种有意义的函数名和变量名,而不用明确指明printf和errno在标准C库中的地址。当然,为了将程序员从早期直接使用地址编程的梦魇中解救出来,编译器和汇编器在这当中做出了革命性的贡献。编译器和汇编器的出现使得程序员可以在程序中使用更具意义的符号来为函数和变量命名,这样使得程序在正确性和可读性等方面都得到了极大的提高。但是随着C语言这种支持分别编译的程序设计语言的流行,一个完整的程序往往被分割为若干个独立的部分并行开发,而各个模块间通过函数接口或全局变量进行通讯。这就带来了一个问题,编译器只能在一个模块内部完成符号名到地址的转换工作,不同模块间的符号解析由谁来做呢?比如前面所举的例子,调用printf的用户程序和实现了printf的标准C库显然就是两个不同的模块。实际上,这个工作是由链接器来完成的。

链接是将各种代码和数据部分收集起来并组合成一个单一文件的过程,这个文件可以被加载到存储器执行。

为了解决不同模块间的链接问题,链接器主要有两个工作要做――符号解析和重定位:

符号解析:当一个模块使用了在该模块中没有定义过的函数或全局变量时,编译器生成的符号表会标记出所有这样的函数或全局变量,而链接器的责任就是要到别的模块中去查找它们的定义,如果没有找到合适的定义或者找到的合适的定义不唯一,符号解析都无法正常完成。

重定位:编译器在编译生成目标文件时,通常都使用从零开始的相对地址。然而,在链接过程中,链接器将从一个指定的地址开始,根据输入的目标文件的顺序以段为单位将它们一个接一个的拼装起来。除了目标文件的拼装之外,在重定位的过程中还完成了两个任务:一是生成最终的符号表;二是对代码段中的某些位置进行修改,所有需要修改的位置都由编译器生成的重定位表指出。

链接分为两种:静态链接和动态链接。

静态链接就是将所有目标文件链接成一个可执行文件,这个可执行文件包含所有的目标文件的拷贝。

动态链接是指在链接阶段并不拷贝动态库的代码和数据节到可执行文件中,只是拷贝一些重定位和符号表的信息,在运行的时候重定位动态库的文本和数据。

说到静态链接和动态链接就不能不说静态库和动态库。

1. 静态函数库

    这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

2. 动态函数库

    这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。 
linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。

创建可执行程序的过程中,静态库同时被链接到程序代码,被主程序调用的函数目标文件连同主程序组合成单一的可执行程序。静态库只在程序链接时起作用,最终的执行程序脱离静态库运行。

使用动态库创建执行程序,分为两个阶段:

链接阶段,即通过ld 创建执行程序时,链接编辑器会在指定的动态库中搜索、解析被主程序调用的函数及其他变量等,如引用被找到,则在执行程序的XCOFF 头结构的loader 区域,建立包含引用的动态库的影像,反之,如在指定的动态库中没有找到此引用的定义,编译器会给出类似未定义的符号引用错误。这不同于静态库,包含引用的目标文件并不和执行程序链接在一起。

另一阶段为运行阶段,即执行程序运行时。程序运行时,系统相关模块将读取定义执行程序的XCOFF 头结构中的信息,查找并加载相关的动态库,假设,所有被应用的动态库都被定位且加载后,程序将开始运行。反之,如果,被应用的动态库丢失,则程序报错。这一个过程我们常称之为动态链接。


为什么系统要支持库的概念?

一方面是为了方便开发人员对标准函数的开发升级,另一方面是方便了应用程序员对标准函数的调用,同时减少了存储器空间的开销。相关的函数被编译成单独的目标模块,然后封装成一个单独的库文件,应用程序可以通过在命令行上指定单独的文件名字来调用在这些库中定义的函数。实际上,c编译器总是会传送libc.a给连接器,所以一般我们不用显式的引用libc.a。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值