Linux操作系统--显示运行时链接

1,显示运行时链接的优点

使得模块组织更加灵活,可以在使用的时候再进行加载,不需要的时候进行释放。

另外,模块可以进行更新而不需要停止程序的运行。这对诸如Web服务器等需要长时间运行的程序非常重要。例如Web服务器的某个模块更新了,则仅仅需要通知Web服务器对该模块进行重新动态加载就可以了。

2,动态库与共享对象的区别

共享对象是动态链接器在程序开启的时候进行加载和链接的,这一系列的步骤都是对程序本身透明的。动态库则是通过一系列的动态链接器提供的API,具体有4个:dlopen,dlsym,dlerror,dlclose,程序可以通过这几个API对动态库进行操作。

它们的实现在/lib/libdl.so.2里边,相关声明和常量在<dlfcn.h>。

2,dlopen

void * dlopen(const char *filename ,int flag);

如果传入的文件参数是0,那么dlopen返回的是全局符号表的句柄。也就是说可以运行时找到全局符号表的任何符号,执行它们。

这有些类似高级语言(比如Java,嘿嘿还好我学过)的反射机制。全局符号表包含程序的可执行文件、动态加载的共享模块和dlopen打开的共享库并且使用了RTLD_GLOBAL方式的模块中的符号。

第二个是符号解析方式。RTLD_LAZY表示使用延迟绑定(PLT);RTLD_NOW模块加载时进行绑定,如果有绑定失败,则dlopen返回错误。上边两种必选一个。另外可以使用RTLD_GLOBAL来与上述两个“或”,表示被加载的模块的全局符号合并到进程的全局符号表,使得以后加载的模块可以使用这些符号。

dlopen返回加载的模块的句柄,在dlsym和dlclose时需要。加载失败返回NULL。如果模块已经加载,返回同一个句柄。如果依赖于其他模块,程序员需要手工加载依赖模块。

另外dlopen会执行.init段的代码以进行模块初始化。

3,dlsym()

核心部分,用以找到符号。

void *dlsym(void *handle.char *symbol);

一个是模块句柄,一个是符号名称。没找到返回NULL,否则返回符号的值。

值的意义:函数则是函数地址,变量则是变量地址,常量则是常量值。如果常量本就是NULL或者0.则需要通过dlerror判断是找到符号而符号值是NULL还是没有找到符号返回了NULL。dlerror返回NULL表示没有发生错误。

常量符号一般是编译链接器产生的,对外不可见。比如编译单元文件名。使用objdump -t查看,常量在符号表中类型是 *ABS*。

4,符号查找优先序列

对于ld加载的模块,符号如果存在冲突,则先装入的优先。dlopen装入的符号也可能与之前的模块重复。进行符号解析和重定位时,ld同样采取了装载序列。dlsym()对符号查找分为两种: 传入的文件参数是NULL的时候,此时使用的是全局符号表;dlsym是使用装载序列的;如果不是NULL,则以打开对象的符号表为根节点,进行依赖文件的广度优先遍历。

dlerror判断dlopen、dlsym和dlclose的上次调用是否成功。返回是char *,如果是NULL则无错;否则是错误信息的指针。

5,dlclose()

系统维持一个模块的加载计数,dlclose使得计数-1,如果为0,就真正被卸载。卸载先执行.finit代码,然后将符号从符号表去除,取消进程地址空间和模块的映射关系,关闭模块文件。

6,gcc中的-ldl

gcc -o RuntimeSimple RuntimeSimple.c -ldl

-ldl表示使用 DL(动态加载)库,位于/lib/libdl.so.2。

7,函数的执行

知道函数的地址,还必须知道函数签名才能执行该函数(签名中有返回值、参数的信息)。Java等中的反射机制,可以获取函数的额外信息,包括函数的参数、返回值。但是C/C++没有保存这些信息到可执行、共享库或者目标文件(当然从符号修饰中可以知道)。所以,一般开发人员必须知道函数的原型。

8,程序员自我修养288页有个程序,可以根据传入参数和符号,执行该符号的函数。

由于预先不知道要执行的函数的参数的个数和各个参数类型,所以使用了汇编,根据输入的参数顺序依次压栈,然后跳转到函数符号地址处执行。 这种方式就伪造了函数调用的堆栈,然后使用无参数的该函数的指针,调用该函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值