动态链接知识点

Posted Virtual_Func

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态链接知识点相关的知识,希望对你有一定的参考价值。

1.基本思想:

动态链接的基本思想是:将链接的过程推迟到运行时再执行。


2.动态链接文件的格式:

在LINUX 中,ELF的动态链接文件被称为动态共享对象(DSO,dynamic shared object),以.so为扩展名的文件

在WINDOWS中,EP的动态链接文件被称为动态链接库(DLL,dynamic link library),以 .dll 为扩展名的文件


3.静态链接器与动态链接文件

在链接的过程中,也需要将动态链接文件作为链接器的输入文件之一,链接器在解析符号时就可以知道哪些符号是定义在动态链接文件中的动态符号,这样链接器就可以对动态符号的引用做特殊处理,使它称为一个特殊的引用。


4.动态链接程序运行时地址空间分布

在动态链接程序运行时,除了可执行文件本身,将还有动态链接文件与动态链接器将被映射到进程的地址空间中,动态链接器被当做普通的共享对象来进行映射,在系统运行可执行文件之前,会将控制权交给动态链接器,由它完成所有的动态链接工作以后再把控制权交给可执行文件


5.共享对象的装载地址

共享对象的最终装载地址在编译时是不确定的,而是在装载时,装载器根据当前地址空间的空闲情况,动态的分配一块足够大小的虚拟地址空间给相应的共享对象


6.共享对象的装载地址的确定方法:

6.1固定共享对象装载地址

概述:程序员手动指定或者由操作系统给共享对象分配固定的装载地址

缺陷:

a) 地址冲突:假设A程序员开发模块a时,将其的地址固定在0x1000到0x2000,B程序员开发模块b时,也将其地址固定在了相同的位置,则现在程序员C开发的程序需要同时用到 a 与 c 模块,那就无法解决这个问题了。

b) 静态共享库的升级:

SSL(static shared library):静态共享库将程序的各种模块统一交个操作系统来管理,操作系统在某个特定的地址划分出一些地址块,为已知的模块预留足够的空间。

缺陷:升级后的共享库中的全局变量和变量地址必须不变,否则应用程序在链接时已经绑定了该地址,修改后必须重新连接程序;且分配的空间有限


6.2 装载时重定位(LTR,load time relocation)

 概述:在链接时,对所有绝对地址的引用不做重定位,把这一步推迟到装载的时候进行;一旦模块装载地址确定,即目标地址确定,则系统对程序中所有的绝对地址的引用进行重定位。

*注:这种方式的重定位时,共享对象的整个程序是按照一个整体进行加载的,因此,程序中的指令与数据的相对位置是不会改变的。对于程序中的某些指令,将经过重定位后修改指令中的绝对地址

eg:

如果一个程序在编译时,假设目标地址为0x1000,但在装载的时候操作系统发现0x1000已经被占用,且从0x4000开始有一块足够大的空间可以容纳该程序,则就将该程序装载到0x4000,则程序中指令和数据中的所有绝对引用都只要再加上0x3000的偏移量就可以了

缺陷:

装载时重定位的方法需要修改指令,而动态链接模块被装载至虚拟空间后,指令部分是在多个进程之前共享的,所以装载时重定位的方法无法共享对象。

*个人还暂时没有想明白,为什么需要修改指令,既然程序是作为一个整体加载的,为什么不使用相对地址,而且,重定位的时候为什么会需要修改指令,CSDN中有人回答说是:因为可能会出现对模块内全局对象的引用,而模块内全局对象就必须是一个在重定位时修改的量。。。好困惑啊啊啊啊啊啊!!!!!!!!!

以上是关于动态链接知识点的主要内容,如果未能解决你的问题,请参考以下文章

动态链接知识点

如果链接未注册,Firebase 动态链接默认行为

如何动态地向promises链添加新的承诺

在C回调中的C ++中引发异常,可能会跨越动态库边界……是否安全?

Linux程序编译链接动态库版本号的问题

如何从手动创建的 Firebase 动态链接中收集统计信息?