DSO(dynamic shared object)动态共享对象的原理

原创 2013年12月02日 10:40:22


摘要:可执行ELF文件的生成,如果从源文件c开始算起,需要经过编译、链接、装载几个步骤。在链接和装载这两个步骤中,有两种不同的实现方式,一种是静态链接,这样加载之前,已经形成可执行目标文件;另外一种是动态链接,这种模式下,链接阶段只是链接一部分目标文件,动态链接库(DSO)在装载的时刻才会映射到进程地址空间。本文主要讲解DSO的原理。


1.装载过程涉及的问题

当程序被装载时,系统的动态链接器会将程序所需的所有动态链接库(例如最基本的libc.so)装载到进程的地址空间,且将程序中所有为决议的符号绑定到相应的动态链接库中,并进行重定位工作(术语叫装载时重定位-load time relocation,在windows中,又叫基址重置-rebasing,区别于静态链接的链接时重定位-link time relocation)。也即,动态链接是把可执行elf的形成过程从本来的程序链接前推迟到装载时。共享对象的最终装载地址在编译时是不确定的,而是在装载时,装载器根据当前地址空间的空闲情况,动态分配一块足够大小的虚拟地址空间给相应的共享对象。        

        装载时重定位的问题:so文件被load并映射至虚拟空间后,指令部分通常是多个进程间共享的,通常的装载时重定位是通过修改指令实现的(主要是根据情况修改指令中涉及到的地址),所以无法做到同一份指令被多个进程共享(因为指令被重定位后对每个进程来讲是不同的)。这样一来,就失去了动态链接节省memory的一大优势。

         为解决此问题,引入了地址无关代码(PIC,Position-independent Code,详细概念见wikipedia)的技术,基本思路是把指令中那些需要被修改的部分分离出来,跟数据部分放到一起,这样,剩下的指令就可以保持不变,而数据部分在每个进程中拥有一个副本。ELF针对各种可能的访问类型(模块内部指令调用、模块内部数据访问、模块间指令调用、模块间数据访问),实现了对应地址引用方式,从而实现了PIC。

        对应到实际应用中,我们可以在编译时指定-fPIC参数让gcc产生地址无关码。


2.印象动态链接性能的因素


        a. 与静态链接相比,动态链接对全局和静态的数据访问都要进行GOT(Global Offset Table,实现PIC时引入的具体技术)定位,然后间接寻址;对于模块间的调用也要先定位GOT,然后间接跳转,如此,程序的运行速度就会减慢

       b. 程序装载时,动态链接器要进行一次链接工作,即查找并装载所需的共享对象,然后进行符号查找、地址重定位等工作,这会减慢程序启动速度

       一方面,程序模块往往包含了大量的函数调用,从而导致动态链接器在模块间函数引用的符号查找及重定位方面耗费时间;另一方面很多函数并不会在程序运行初期就用到(尤其是有些异常处理函数),由此,EFL采用延迟绑定(lazy binding)来对动态链接做优化,其基本思想是当函数第一次被调用时才进行绑定(符号查找、重定位等),若没有被调用则不进行绑定。这个思路可以大大加快程序启动速度,对于有大量函数引用的程序启动时,尤为明显。具体到实现,EFL采用PLT(procedure linkage table)来实现,具体过程很是精妙复杂,本文只是抛砖引玉,不再详述,有兴趣的同学可以用PLT英文关键字google相关资料



3.疑问

1)是否能够用地址映射共享DSO内存

同一份指令应当是指的共享模块中的指令吧?如果是的话,那么各个进程无论将共享模块装载至进程虚拟地址空间的何处,只要在该进程装载时对共享模块中地址的引用执行重定位,即使装载的地址不一样,重定位之后也是各个进程的中的代码对共享模块引用地址的不同,而共享模块中的代码是不需要变化的?


分析:简而言之,DSO是不是可以不修改代码,而是通过将不同进程的虚拟地址映射到同一个区域的物理地址来实现,DSO的共享?


不要忘了,装载进去的都是指令,也就是一行行的“汇编代码”:

mov eax, [0x123456]

很显然,如果DSO引用了外部模块的地址,那么这个地址的变量值总是随着整个进程空间布局的不同而变化。那么,这个问题就不是能用linux内核的内存管理中虚实地址的映射能够解决的了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

静态库(Archive Libraries)和动态库(Shared Object)的基本知识

linux下编译,常会遇到后缀为:.o .so .a .la .ko等格式文件,尽管linux并不以扩展名作为识别文件格式的唯一依据,但规范约定还是有的,如下: .o 是目标对象文件,相当于wind...

aix中使用xlc编译生成动态链接库(shared object)(.so)文件的方法

今天写一个ppt的时候,忽然发现不会用xlc编译成出.so文件,于是baidu,未果。 后cc看了一些命令的选项后,查到了编译的选项 。 假设我有hellofirst.c和hellosecond....

C++对象动态生成(Dynamic Create)的简单实现

以前一直是C++的coder,最近由于到了另一家公司,因此开始写java项目,相信C++的程序员都会对java语言原生支持的动态生成很是羡慕,但是C++不支持反射(reflection),也就无法根据...

Json.net实现方便的Json转C#(dynamic动态类型)对象

以前需要将一段json字符串转换为C#对象时,一般都是定义一个与之对应的实体类来接收。这样做有一个很大的缺点,就是当字符串特别长,属性特别多,又有嵌套时,手敲这个实体类就非常痛苦。 比如之前做的一个接...

关于对象动态类型的一些问题 Object-C 2.0

关于对象动态类型的一些问题 Object-C 2.0 To get a class object from a class named  Square , you write...

shared object

  • 2009-01-21 11:00
  • 39KB
  • 下载

C#动态对象(dynamic)示例(实现方法和属性的动态)

C#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种动态方法的实现,看起来有点j...

nginx 动态加载(ngx_dso_module)模块

根据 tengine 官网的介绍 ngx_dso_module 模块主要是用来运行时动态加载模块,而不用每次都要重新编译Tengine。动态加载模块的个数限制则为128个,如果已经加载的动态模块有修改...

安装PHP三种安装方式静态模式、动态模式(DSO)、CGI二进制模式。

我们在使用PHP时,通常都会与Apache一起使用。那么,如何能够将二者很好的融合在一起呢?我们接下来就向大家介绍如何实现PHP安装为Apache的。在安装PHP时,有三种安装方式可供选择:静态模式、...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)