Linux动态库的动态加载与静态加载以及加载依赖了其他动态库的动态库

Linux动态库加载

在Linux下,动态库格式一般为libxxx.so者libxxx.so.3这种格式。
通常我们在网上下载下来源码包,编译之后会是libxxx.so软连接libxxx.so.1链接libxxx.so.1.23这种形式。.so后面分别大版本和小版本含义。
在加载动态库时一般有静态和动态两种加载方式:
1.静态加载(隐式加载):在链接时将其链接进目标文件。
链接分两种:

  • 指明具体库文件径,如“/home/test/libxxx.so”,在链接时就会自动链接该文件。
  • 使用系统路径,如"/lib","/usr/lib","/usr/local/lib","/lib/x86_64-linux-gnu"以及使用LD_LIBRARY_PATH等环境变量含的径

在编译时的格式如:
绝对路径或相对径:g++ test.cpp -o test /home/test/libxxx.so -I /home/test/include
对于指明路径的,直接写上路径即可。-I(大写i)参数后面加上编译所需要的头文件。
系统路径:g++ test.cpp -o test -lxxx
对于系统路径下的动态库,libxxx.so这种形式的库可以直接使用-l(小写L)跟上lib后面“xxx”来进行链接,编译器会自动在系统目录中寻找。
2.动态加载(显式加载):
在程序中动态加载动态库,当运行到加载处时,才会将动态库加载进来。
动态加载需要包含的头文件:#include<dlfcn.h>
①打开动态链接库:

void *dlopen (const char *filename, int flag);
flag:
RTLD_NOW:在dlopen返回前,解析出全部没有定义的符号,解析不出来返回NULL。
RT_GLOBAL:动态库定义的符号可被其后打开的其他库解析。
RT_LOCAL:和上面相反,不能被其他库解析。默认。
RTLD_LAZY:暂缓决定,等有需要时再解出符号

返回值:
打开错误返回NULL
成功,返回库引用
②取函数:

void *dlsym(void *handle, char *symbol); 
将dlopen返回的句柄传入dlsym的handle,symbol参数则是要是用的符号(函数名)

③关闭动态链接库:

int dlclose (void *handle); 
returns 0 on success, and nonzero on error.

用于关闭对应句柄的动态库,释放资源
只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
示例:

void *handle;
int (*function_add)(int,int);
char *error;
handle = dlopen ("/home/test/libxxx.so", RTLD_LAZY);  
if (!handle) {  
	fprintf (stderr, "%s ", dlerror());  
	exit(1);  
}  

function_add = (int(*)(int))dlsym(handle, "add");  

示例2:

test.h
typedef int   (*Add)( int a,int b);
static Add add= NULL;


test.cpp
void *handle;
handle = dlopen ("libadd.so", RTLD_LAZY);  
if (!handle) {  
	fprintf (stderr, "%s ", dlerror());  
	exit(1);  
}  
add=(*Add)dlsym(handle,"Add");

复杂情景:
程序使用动态库a时,动态库a又使用了动态库b
静态加载:
动态库b需要在系统目录下或者在动态库a编译时指定链接的路径下。
动态加载:
可以在程序中先动态加载动态库b,即dlopen(“libb.so”);之后再dlopen(“liba.so”);之后再进行动态库a的函数地址获取与使用。

测试:
编译好一个libpng.so之后,使用ldd查询其依赖的libz.so的位置:
在这里插入图片描述
刚刚编译出来时,链接的libz指向了编译时寻找的/usr/local/lib/libz.so(注:编译时记得添加-fPIC指明动态库与位置无关)
在这里插入图片描述
将/usr/local/lib/libz.so删除后,再次使用ldd,发现又指向了系统目录下的libz。同时运行动态加载了libpng的test程序,仍可以正常运行
在这里插入图片描述
再次将系统目录下的libz.so删除后,使用ldd无法找到libz.so,同时运行test程序会提示找不到依赖。
修改test的代码,在动态加载同目录的libpng之前,先动态加载同目录下的libz。编译后运行成功。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值