为什么要使用动态链接?
- 静态链接使得不同的部门可以开发不同的模块,极大的提高了开发的效率。但是随之带来了空间浪费,和更新复杂的问题。空间浪费:静态链接讲求的是合并,将多个文件进行合并成一个可执行文件,其中可能包含了库文件。一个可执行文件合并库文件一次,一千个可执行文件合并了一千次,将这些文件都载入内存,这就造成了极大的空间浪费。程序的发布更新造成困扰:比如一个程序有二十个模块,任何的一点改动,就会导致整个程序被下载。极不好的用户体验。
解决这些问题,就是把程序的模块相互分割开来。即不对组成程序的那些目标文件进行链接,等到程序运行时才链接。这样就不会出现许多重复的内容,更新一个模块理论上只需要覆盖原模块即可。把链接这个过程推迟到运行时再进行,这就是动态链接的思想。 静态链接是合并为一个可执行文件载入内存,动态链接则是需要哪一个模块就载入该模块,再进行重定位。
动态链接的方式使开发过程中模块间更加独立,耦合度更小,便于不同的开发者和开发组织之间独立进行开发和测试。
动态链接的一个特点就是动态的加载程序的模块,这个特点后来被人们用来制作插件。一个公司开发一个产品,定义好相关接口后,其他第三方公司就可以根据这些接口来编写动态链接文件,从而实现功能的扩展。--程序的可扩展性。
动态链接的基本实现
在Linux系统中,ELF动态链接文件被称为动态共享对象。常用的C语言库的运行库glibc,在Linux中,文件名叫做“libc.so"。 整个系统只保留一份C语言库的动态链接文件"libc.so",而所有的C语言编写的、动态链接的程序都可以在运行时使用它。当程序被装载的时候,系统的动态链接器会将程序所需要的所有动态链接库(最基本的就是libc.so)装载到进程的地址空间,并且将程序中所有未决议的符号绑定到相应的动态链接库中,并进行重定位工作。程序与libc.so之间真正的链接工作是由动态链接器完成的,而不是由我们前面看到过的静态链接器ld完成的。也就是说,动态链接是把链接这个过程从本来的程序装载前被推迟到了装载的时候。可能有人会问,这样的做法的确很灵活,但是程序每次被装载时都要进行重新进行链接,是不是很慢?的确,动态链接会导致程序在性能的-些损失,但是对动态链接的链接过程可以进行优化,可减少这种损失。
gcc 编译时 -shared 参数就是将该文件产生为共享对象。
另一个值得关注的共享对象:ld-2.6.so ,它是linux下的动态链接器。动态链接器与普通共享对象一样被映射到了进程的地址空间,在系统开始运行程序之前,首先会把控制权交给动态链接器,由它完成动态链接工作以后,再把控制权交给程序。共享对象的最终装载地址在编译时是不确定的。
静态链接在链接时就分配了虚拟地址空间,那么共享对象在被装载时,如何确定它在进程虚拟地址空间的位置?
装载时重定位,一旦模块装载地址确定,即目标地址确定,那么系统就对程序中所有的绝对地址的引用进行重定位,这时候的重定位比较简单,因为整个程序是按照一个整体加载的,程序中指令和数据的相对位置是不会改变的。(仔细体会)
标签:程序,装载,so,模块,动态,链接 From: https://www.cnblogs.com/wuyun--wy/p/16990527.html