Linux 操作系统动态库剖析
必要的再定位,包括目标共享对象所使用的共享对象.LD_LIBRARY_PATH 环境变量定义查找可用共享对象的位置.定义完成后,控制权会被传回到初始程序以开始执行.
再定位是通过一个称为 Global Offset Table(GOT)和 Procedure Linkage Table(PLT)的间接机制来处理的.这些表格提供了 ld-linux.so 在再定位过程中加载的外部函数和数据的地址.这意味着无需改动需要间接机制(即,使用这些表格)的代码:只需要调整这些表格.一旦进行加载,或者只要需要给定的函数,就可以发生再定位(稍候在 用 Linux 进行动态加载 小节中会看到更多的差别). 再定位完成后,动态链接器就会允许任何加载的共享程序来执行可选的初始化代码.该函数允许库来初始化内部数据并备之待用.这个代码是在上述 ELF 映像的 .init 部分中定义的.在卸载库时,它还可以调用一个终止函数(定义为映像的 .fini 部分).当初始化函数被调用时,动态链接器会把控制权转让给加载的原始映像.
用 Linux 进行动态加载 Linux 并不会自动为给定程序加载和链接库,而是与应用程序本身共享该控制权.这个过程就称为动态加载.使用动态加载,应用程序能够先指定要加载的库,然后将该库作为一个可执行文件来使用(即调用其中的函数).但是正如您在前面所了解到的,用于动态加载的共享库与标准共享库(ELF 共享对象)无异.事实上,ld-linux 动态链接器作为 ELF 加载器和解释器,仍然会参与到这个过程中. 动态加载(Dynamic Loading,DL)API 就是为了动态加载而存在的,它允许共享库对用户空间程序可用.尽管非常小,但是这个 API 提供了所有需要的东西,很多困难的工作是在后台完成的.表 1 展示了这个完整的 API. 表 1. Dl API
该过程是调用 dlopen,提供要访问的文件对象和模式.调用 dlopen 的结果是稍候要使用的对象的句柄.mode 参数通知动态链接器何时执行再定位.有两个可能的值.第一个是 RTLD_NOW,它表明动态链接器将会在调用 dlopen 时完成所有必要的再定位.第二个可选的模式是 RTLD_LAZY,它只在需要时执行再定位.这是通过在内部使用动态链接器重定向所有尚未再定位的请求来完成的.这样,动态链接器就能够在请求时知晓何时发生了新的引用,再定位可以正常进行.后面的调用无需重复再定位过程. 还可以选择另外两种模式,它们可以按位 OR 到 mode 参数中.RTLD_LOCAL 表明其他任何对象都无法使加载的共享对象的符号用于再定位过程.如果这正是您想要的的话(例如,为了让共享的对象能够调用原始进程映像中的符号),那就使用 RTLD_GLOBAL 吧. dlopen 函数还会自动解析共享库中的依赖项.这样,如果您打开了一个依赖于其他共享库的对象,它就会自动加载它们.函数返回一个句柄,该句柄用于后续的 API 调用.dlopen 的原型为:
有了 ELF 对象的句柄,就可以通过调用 dlsym 来识别这个对象内的符号的地址了.该函数采用一个符号名称,如对象内的一个函数的名称.返回值为对象符号的解析地址:
如果调用该 API 时发生了错误,可以使用 dlerror 函数返回一个表示此错误的人类可读的字符串.该函数没有参数,它会在发生前面的错误时返回一个字符串,在没有错误发生时返回 NULL:
,如果无需再调用共享对象的话,应用程序可以调用 dlclose 来通知操作系统不再需要 |
|||||||||||||
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |