1. 编译参数
1.1 -fPIC
告诉编译器产生与位置无关代码.如果不加-fPIC,则加载.so文件的代码段时,代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy。每个copy都不一样,取决于这个.so文件代码段和数据段内存映射的位置。不加fPIC编译出来的so,是要再加载时根据加载到的位置再次重定位的.(因为它里面的代码并不是位置无关代码) 如果被多个应用程序共同使用,那么它们必须每个程序维护一份so的代码副本了。
1.1 -rdynamic
1、是一个链接器选项,当将所有的*.o和库链接到最终可执行文件中就使用了它。该参数的作用是:将指示连接器把所有符号(而不仅仅只是程序已使用到的外部符号,但不包括静态符号,比如被static修饰的函数)都添加到动态符号表(即.dynsym表)里,以便那些通过dlopen()或backtrace()(这一系列函数使用.dynsym表内符号)这样的函数使用。
2 动态链接库使用函数如下
- //编译时候要加入 -ldl (指定dl库)
-
- //包含的头文件
- #include
-
-
- void *dlopen(const char *filename, int flag);
- //dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄
- //参数filename是共享库文件的路径,可以是相对路径或绝对路径。参数flag用于指定打开方式,常用的取值包括RTLD_NOW(立即解析所有符号)、RTLD_LAZY(懒加载,只有当使用时才解析符号)等。
- mode: 参数必须包括以下两个值中的一个
- RTLD_LAZY 暂缓决定,等有需要时再解出符号
- RTLD_NOW 立即决定,返回前解除所有未决定的符号。
-
- mode也可以通过以下零或多个值进行或运算设置
- RTLD_LOCAL
- RTLD_GLOBAL 允许导出符号
- RTLD_GROUP
- RTLD_WORLD
- void *dlsym(void *handle, const char *symbol);
- //根据动态链接库操作句柄与符号,返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数或全局变量的名称.
-
- int dlclose(void *handle);
- //用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
-
- char *dlerror(void);
- //当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
3. 动态库函数的使用demo记录
3.1 动态库demo的头文件和源文件
3.1.1 libdemo.h头文件
- #ifndef _LIBDEMO_H_
- #define _LIBDEMO_H_
-
- #include
-
- typedef struct
- {
- int val;
- }Val_t;
-
- extern void add(Val_t* addval);
- extern int getVal(void);
-
- #endif
3.1.2 libdemo.c 文件
- #include "libdemo.h"
-
- int g_libValue = 0;
-
- void add(Val_t *addval)
- {
- g_libValue += addval->val;
- }
-
- int getVal(void)
- {
- return g_libValue;
- }
3.1.3 makefile 简易编写
- src=$(wildcard ./*.c) #把所有以.c文件 匹配上,并把文件名提取出来,作为一个列表赋值给src
- object=$(patsubst %.c,%.o,$(src)) #将src里的每个文件都由.c替换成.o
- target1=libdemo0.so #库文件
- target2=libdemo1.so
- CC=gcc
- CFLAGS=-I./ -shared -fPIC #头文件参数、动态链接编译参数
- all:$(target1)
- $(target1):$(object)
- $(CC) -o $@ $^ $(CFLAGS) #生成动态库文件
- cp $(target1) $(target2) #拷贝一个一样的动态库
- #参数解释, $@表示目标文件
- #参数解释, $^表示所有的依赖文件
- #参数解释, $<表示第一个依赖文件
- %.o:%.c
- $(CC) -o $@ -c $< $(CFLAGS) #生成obj文件
- .PHONY:clean
- clean:
- rm -f $(target1) $(target2) $(object) #清除动态库文件和obj文件
3.2 应用层调用头文件和源文件
3.2.1 appldemo.h头文件
- #ifndef _APPL_DEMO_H_
- #define _APPL_DEMO_H_
-
- #include "libdemo.h"
-
-
- //调用动态库操作函数
- typedef struct
- {
- void (*p_add)(Val_t*);
- int (*p_getval)(void);
- } SharedObjOps_t;
-
-
- extern int SharedObjInit(int id, SharedObjOps_t*op);
-
- #endif
3.2.2 appldemo.c源文件
- #include
- #include
- #include
- #include
-
-
- #define FILE_PATH_NAME "../lib/libdemo"
-
-
- /*
- * brif :调用动态库初始化函数
- */
- int SharedObjInit(int id, SharedObjOps_t*op)
- {
- char filePathName[128] = FILE_PATH_NAME;
- char idnum[10] = {0};
- char filetype[10] = ".so";
- char file[128] = {0};
- void *handle; //库文件句柄
-
- strcat(file, filepath);
-
- sprintf(idnum, "%d", id);
- strcat(file, idnum);
- strcat(file, filetype);
-
- handle = dlopen(file, RTLD_LAZY); //打开动态库,且为暂缓决定,等有需要时再解出符号
-
- if (handle == NULL)
- {
- return 1; //打不开库
- }
-
- op->p_add= dlsym(handle, "add");
- op->p_getval= dlsym(handle, "getval");
-
- if(!op->p_add || !op->p_getval)
- {
- return 2; //找不到其中的库函数
- }
-
- return 0;
- }
-
-
-
- int main()
- {
- SharedObjOps_t op0, op1; //两个动态库操作函数结构体句柄
- Val_t val0 = {0}, val1 = {0};
-
- //分别初始化两个动态库
- if(SharedObjInit(0, &op0))
- {
- return 1; //失败
- }
- if(SharedObjInit(1, &op1))
- {
- return 1; //失败
- }
-
- val0.val = 10;
- val0.val = 20;
-
- op0.p_add(&val0);
- op1.p_add(&val1);
-
- printf("op0's g_libValue returned: %d\n", op0.p_getval());
- printf("op1's g_libValue returned: %d\n", op1.p_getval());
-
-
- val0.val = 1;
- val1.val = 2;
-
- op0.p_add(&val0);
- op1.p_add(&val1);
-
- printf("op0's g_libValue returned: %d\n", op0.p_getval());
- printf("op1's g_libValue returned: %d\n", op1.p_getval());
-
- return 0;
- }
3.2.3 Makefile编写
- src=$(wildcard ./*.c)
- object=$(patsubst %.c,%.o,$(src))
- target=appdemo
- CC=gcc
- CFLAGS=-I./ -I../lib -ldl
- all:$(target)
- $(target):$(object)
- $(CC) -o $@ $^ $(CFLAGS)
- %.o:%.c
- $(CC) -o $@ -c $< $(CFLAGS)
- .PHONY:clean
- clean:
- rm -f $(target) $(object)