有很长一段时间都是有使用别人写好的library,还从来没有认真的写过一个library,原来以为写这个东东是简单,可是真的让你自己做,还是有一定的难度,需要了解很多相关知识
那么在linux下library到底有什么曲折呢,还是从如何使用开始吧!
在Linux下有两种library,分别是静态库(lib*.a),还有就是动态库(lib*.so)。我们在使用的时候只要在编译的时指定所需要的库文件就可以了,如下:
gcc -c main.c -lpthread main
如此就可以了,这种方式你可能感觉到有点不是很理解,我知道有关pthread的库文件是libpthread.so(如果是静态库,那么是libpthread.a),而你只在里面用到一个-lpthread就OK了?哈:如果这进了不知道,那就回去看看gcc中编译选项了!
上面只是说明一下如何使用这个library罢了。那么下面我们就进入如何生成自己的library的项目了!
- 静态库(lib*.a)
什么是静态库,他有什么特点?
静态链接库其实就是把一个或多个目标文件(即编译生成的.o文件)归档在一个文件中。此后,当需要使用这个静态库中的某个功能时,将这个静态库与要生成的 应用程序链接在一起。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下。
由上面的定义可以看出,
由静态库编译出来的程序的体积大。但是已经编译的程序不依赖库文件。
静态库体积也很大。
- 动态库
程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那 一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系 统中所有运行的程序共享着同一个C标准库的代码段。
动态库的优点与缺点都已经有上面的定义中了。
那么如何创建自己的库文件呢?
- 静态库的创建
创建静态库,使用命令ar:
使用范例如下 --------ar -cqs libexample.a example.o
ar命令中使用的几个参数解释如下:
c :创建一个lib文件
q:append quickly
s:建立索引
- 动态库的创建
动态库的创建是gcc直接编译创建
gcc -shared -fPIC -o libexample.so example.o
还有一种很有用的方法,我们在编写程序的时候很可能不确定一个方法的最终实现方式,但是我们函数的名称已知,如果我们可以从现代一个给定的so中直接获取函数的最终实现。
如何处理?
过程中会用到如下的函数,
使用dlopen打开so文件,然后再使用现有现有的ldsym获取库文件里面的函数实现,在处理结束时,需要关闭现有so文件。
几个常用的函数实现如下!
LINUX下使用动态链接库, 源程序需要包含dlfcn.h头文件, 此文件定义了调用动态链接库的函数的原型.下面详细说明一下这些函数.
1. dlerror
原型为: const char *dlerror(void);
当动态链接库操作函数执行失败时, dlerror可以返回出错信息, 返回值为NULL时表示操作函数执行成功.
2. dlopen
原型为: void *dlopen (const char *filename, int flag);
dlopen用于打开指定名字(filename)的动态链接库, 并返回操作句柄.
filename: 如果名字不以/开头, 则非绝对路径名, 将按下列先后顺序查找该文件.
(1) 用户环境变量中的LD_LIBRARY值;
(2) 动态链接缓冲文件/etc/ld.so.cache
(3) 目录/lib, /usr/lib
flag表示在什么时候解决未定义的 符号(调用).取值有两个:
1) RTLD_LAZY : 表明在动态链接库的函数代码执行时解决.
2) RTLD_NOW : 表明在dlopen返回前就解决所有未定义的符号, 一旦未解决, dlopen将返回错误.
dlopen调用失败时, 将返回NULL值, 否则返回的是操作句柄.
3. dlsym : 取函数执行地址
原型为: void *dlsym(void *handle, char *symbol);
dlsym根据动态链接库操作句柄(handle)与符号(symbol), 返回符号对应的函数的执行代码地址.由此地址, 可以带参数执行相应的函数.
如程序代码: void (*add)(int x,int y); /* 说明一下要调用的动态函数add */
add=dlsym("xxx.so","add"); /* 打开xxx.so共享库,取add函数地址 */
add(89,369); /* 带两个参数89和369调用add函数 */
4. dlclose : 关闭动态链接库
原型为: int dlclose (void *handle);
dlclose用于关闭指 定句柄的动态链接库, 只有当此动态链接库的使用计数为0时,才会真正被系统卸载.
后面会增加例子,今天就到此为止了!
-------------------下次见----------------------