linux下静态链接库,动态链接库,动态加载库问题
linux下这三种库的区别
动态链接库(共享库)和动态加载库区别
- 使用方式
动态链接库是程序运行一开始就要加载库,动态加载库是程序在运行到函数需要这个函数的实现的时候才加载库。所以动态加载库就需要一组函数来控制什么时候加载库。这些函数是
- dlopen()
- dlerror()
- dlsym()
- dlclose()
示例代码:
int (*addFunc) (int a, int b); //声明函数指针,用来接收dlsym返回来的函数
void *phandle = dlopen("libtest.so", RTLD_LAZY);
//参数add是库里定义的add函数,dlsym返回函数地址
addFunc = dlsym(phandle, "add");
printf("%d\n", addFunc(2, 5));
编译的时候:
gcc main.c -o main -ldl
//要加上参数-ldl。dl库是dlopen()等那三个打开库使用的函数。
这时候再编译自己的程序的时候就不用像动态链接库那样 -L./ -ltest,链接自己的test库了,因为程序中需要这个库的时候就打开这个库使用了。
- 内存使用
从编程角度来讲,动态链接库是最方便的,效率上影响也不大,在内存使用上有些差别。
- 动态链接库 :一个库的代码,只要运行过一次,便会占用物理内存,之后即使再也不使用,也会占用物理内存,直到进程的终止。
- 动态加载库:库代码占用的内存,可以通过dlfree的方式,释放掉,返回给物理内存。这个差别主要对于那些寿命很长,但又会偶尔调用各种库的进程有关。如果是这类进程,建议采用第二种方式调用动态链接库.
gcc 生成库的方法
动态链接库
参考文章: http://download.csdn.net/detail/u014132659/9673886 是一个上传的文档
库是目标文件的集合, 目标文件在动态链接库中的组织方式是按照特殊方式形成的,库中函数和变量的地址是相对的,不是绝对地址,其真实地址在调用动态库的程序加载时形成的。安装库文件就是把库文件放在系统目录下,能让程序找见就可以。系统默认的目录是/lib和/usr/lib或者还有其他的。也可以不放在系统默认路径下,自己在链接库配置文件中配置一个路径。
链接库的配置文件,即配置程序运行时查找动态库的路径,配置文件是 /etc/ld.so.conf。系统文件 /lib 和 /usr/lib 是默认的查找的目录,不用配置。其余的自己添加的路径可以配置进去。
动态链接库管理命令ldconfig,运行命令会生成一个在动态库的别名,就是命令里写的 -soname 的名字。重点是这个命令会生成 /etc/ld.so.cache 文件,这个是运行程序时查找动态库的时候需要的。具体这个文件是写了什么东西,还不清楚。
参考文章:http://www.cnblogs.com/xuxm2007/archive/2010/08/10/1796254.html
动态库配置文件 和 LD_LIBRARY_PATH 都是解决程序在运行时查找加载动态库问题的。在编译程序的时候,链接过程还是需要加 -L 和 -l参数,指定动态库的具体位置,链接器需要。(一定不要混淆)。一个是编译时查找动态库,具体是链接阶段,一个是运行时加载动态库。
—命令— 具体示例看上面上传的文档
gcc -Wall -fpic -o libtest.o -c test.c
gcc -shared -Wl,-soname,libtest.so -o libtest.so.0 libtest.o
//-shared参数,-soname生成别名用的,真实名字是.so.0,有版本号
gcc -o main main.c -L./ -ltest
nm lictest.so //查看库提供的函数,T标记
如何编写动态库
linux下使用__attribute__((visibility(“default”))) 导出库函数,类似于Visual C++ 关键字__declspec(dllexport)。windows下如何生成动态库
参考文章中提到"How To Write Shared Libraries"大作,有时间去膜拜下。
静态链接库
生成静态链接库需要用ar命令
—命令—
gcc -c test.c //生成test.o
ar -rcs -o libtest.a test.o //生成静态库
nm libtest.a //查看库提供的函数
nm t libtest.a // 查看库中内容
// 使用
gcc -o main main.c libtest.a
或者
gcc -o main main.c -L./ -static -ltest