美文网首页
五、【热修复一】so插件化实现原理

五、【热修复一】so插件化实现原理

作者: ChiangCMBA | 来源:发表于2018-04-08 23:27 被阅读0次

一个so调用另外一个so中的函数。
通过函数dlopen打开指定的动态链接库,得到句柄后,再通过dlsym函数获取动态库中的函数地址,获得函数地址后进行调用。

1.编写calculate.c

int add(int a,int b){
    return (a+b);
}

2.将calculate.c编译成libcalculate.so

gcc -fPIC -shared calculate.c -o libcalculate.so

-fPIC 压制警告
-shared 动态库
-o 生成目标的文件名

3.编写main.c

#include<stdio.h>

#include<stdlib.h>

#include<dlfcn.h>

typedef int (*ADD)(int, int);
int main(){
        //打开一个动态链接库,并返回动态链接库的句柄
        void *handle = dlopen("./libcalculate.so", RTLD_LAZY);
        ADD add = NULL;
       //获取函数地址
        *(void **)(&add) = dlsym(handle, "add");
        int result = add(8,8);
        printf("Add result:%d\n", result);
        return 0;
}
相关函数说明:

(1).void *dlopen(const char *filename, int mode);
打开一个动态链接库,并返回动态链接库的句柄。
mode是打开方式。
RTLD_LAZY:在dlopen返回前,对于动态库中的未定义的符号不执行解析(只对函数引用有效,对于变量引用总是立即解析)。
RTLD_NOW: 需要在dlopen返回前,解析出所有未定义符号,如果解析不出来,在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......
(2).void *dlsym(void *handle, const char *symbol);
根据 动态链接库 操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。
handle:由dlopen打开动态链接库后返回的指针;
symbol:要求获取的函数或全局变量的名称。(本例中是函数add的名称)

4.编译成可执行文件

gcc -rdynamic -o main main.c -ldl

(1).选项 -rdynamic 用来通知链接器将所有符号添加到动态符号表中(目的是能够通过使用 dlopen 来实现向后跟踪)
(2).如果程序中使用dlopen、dlsym、dlclose、dlerror 显示加载动态库,需要设置链接选项 -ldl

5.运行结果

Linux下so插件化调用.png

相关文章

网友评论

      本文标题:五、【热修复一】so插件化实现原理

      本文链接:https://www.haomeiwen.com/subject/uemuhftx.html