动态库的重复链接
动态库的重复链接
背景
如果现有系统的库有两个层次,底层库和接口库。接口库通过dlopen的方式加载底层库,接口库提供给用户使用。现在需要在用户层调用底层库的接口,应该如何做?
一个解决方案(有问题的)
一个直观地解决方案就是直接给出底层库需要调用的接口的原型,然后直接调用。由于调用接口需要在编译时确定,因此需要显式指定链接库。这种方式的一个问题就是动态库被加载了两次,加载两次的效果通过如下例子可以观察:
例子如下:
/* file: test.c */
int g_value = 1;
/* file: main.c */
#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
extern int g_value;
int main()
{
char libname[] = "libtest.so";
g_value = 0;
printf("value=%d, p=%p\n", g_value, &g_value);
void *handle = dlopen(libname, RTLD_NOW);
if (!handle)
{
printf("dlopen error\n");
return -1;
}
int *value = (int*)dlsym(handle, "g_value");
printf("value=%d, p=%p\n", *value, value);
dlclose(handle);
handle = 0;
return 0;
}
# 编译命令
g++ test.c -shared -fPIC -o libtest.so
g++ main.c -L. -ltest -o main.out
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./main.out
value=0, p=0x5590e7ebe010
value=1, p=0x7f1943211020
显然,这种方式中,两次加载的库的全局变量总共存在两份。这个现象说明,动态库在内存中总共有两份,这可能会引起问题(比如部分资源是需要单例访问)。
合理的解决方案
If the same shared object is opened again with dlopen(), the same object handle is returned. The dynamic linker maintains reference counts for object handles, so a dynamically loaded shared object is not deallocated until dlclose() has been called on it as many times as dlopen() has succeeded on it. Constructors (see below) are called only when the object is actually loaded into memory (i.e., when the reference count increases to 1).
也即,要获得一个被dlopen打开的库里的特定函数,可以直接用dlopen打开即可。不论先后,都不会影响后续的dlopen(当然,不能干扰内部对库的使用)。
posted on 2022-12-20 00:26 amazzzzzing 阅读(328) 评论(0) 收藏 举报