标签:共享 链接库 物理地址 阶段 bsp img 全局 内存地址 共享库
前言:
前面讲过,通过链接将不同文件内的代码合并到一起成为一个可执行文件,才能加载运行,在不同程序链接的过程中,有些代码是被多次复用的,如果每个程序装载的时候都去重复装载这部分代码,就会使这些相同的代码重复占用内存。
(一)链接分动静,共享省内存
要解决这个问题,我们希望不同程序引用相同代码时,都只需装载一次,这就是动态链接;而之前直接合并代码的方式称之为静态链接。动态链接中,链接的是加载到内存中的共享库,在Windows里是.dll文件,在Linux下是.so文件。
二、要想“地址无关”,使用“相对地址”
想要在程序运行时共享代码,那么这些机器码必须是地址无关的。对于所有动态链接共享的程序来说,即使共享库用的是同一段物理内存地址,但在不同的应用程序里其虚拟内存地址也是不同的。动态库编译出的代码指令通过如下方式做到地址无关:
三、PLT和GOT,动态链接的解决方案
编译完成的地址无关的代码文件中,对于共享库函数的调用需要从PLT也就是程序链接表中找到调用的函数。
在共享库的data section中保存了一张全局偏移表GTO,虽然共享库的代码部分物理地址共享,但数据部分是各个动态链接它的应用程序各自加载一份。所有需要引用当前共享库外部地址的指令都会查询GOT,来找到当前运行程序的虚拟内存里的对应位置。
而GOT里的数据,则是在加载一个个共享库时写入的。因此调用同样动态库的不同应用程序各自GOT中最终加载的动态链接库中的虚拟内存地址是不同的。
这样只要各个应用程序维护好自己的GOT就可以共享动态库中的代码,而不需要修改动态库中代码所使用的的地址。
共享库代码部分直接使用,外部变量和函数部分通过各自GOT来计算得到。
总结:
通过使用动态链接,使得代码不仅在编码过程完成了服用,在运行阶段也做到了复用,这一点颇类似于jvm的类装载机制,统一将各个类装载进jvm后再调用,难怪被称为虚拟机,并且jvm是类被使用时才加载,这就更加灵活而且还加快了启动速度、节省了内存空间。
标签:共享 链接库 物理地址 阶段 bsp img 全局 内存地址 共享库
原文地址:https://www.cnblogs.com/rxmind/p/12826681.html