1.什么是库文件?
可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。
库文件一般指计算机上的一类文件,分为静态库和动态库两种。
2.静态库
-
静态库的本质就是将多个目标文件打包成一个文件
-
链接静态库就是将库中被调用的代码复制到调用模块中
-
静态库的拓展名是.a 例:libxxx.a
3.动态库
4.静态库和动态库比较
5.动态库的动态加载
-
在程序执行的过程中,开发人员可以动态加载共享库
-
在程序中动态加载共享库需要调用一组特殊的函数,它们被声明于一个专门的头文件中,并在一个独立的库中予以实现。
-
使用这组函数需要包含此头文件,并链接该库
#include <dlfcn.h>
-ldl
-
void* dlopen(char const* filename, int flag);
功能:将共享库载入内存并获得其访问句柄
参数:filename 动态库路径,若只给文件名不带目录,则根据LD_LIBRARY_PATH环境变量的值搜索动态库
flag 加载方式,可以取下值:
RTLD_LAZY-延迟加载,使用动态库中的符号时才真的加载进内存
RTLD_NOW-立即加载
返回值:成功返回动态库的访问句柄,失败返回NULL
句柄:句柄唯一地标识了系统内核所维护的共享库对象,将作为后续函数调用的参数
-
void* dlsym(void* handle,char const* symbol);
功能:从已被加载的动态库中获取特定名称的符号地址
参数: handle 动态库访问句柄
symbol 符号名
返回值:成功返回给定符号的地址,失败返回NULL
该函数所返回的指针为void* 类型,需要造型为与实际目标类型相一致的指针,才能使用
-
int dlclose(void* handle);
功能:从内存中卸载动态库
参数: handle 动态库句柄
返回值:成功返回0,失败返回非0
所卸载的共享库未必会真的从内存中立即消失,因为其他程序可能还需要使用该库
只有所使用的该库的程序都显示或隐式地卸载了该库,该库所占用的内存空间才会真正的得到释放
无论所卸载的共享库是否真正被释放,传递给dlclose函数的句柄都会在该函数成功返回后立即失效
-
char* dlerror(void);
功能:获取在加载、使用和卸载共享库过程中所发生的错误
返回值:有错误则返回指向错误信息字符串的指针,否则返回NULL
例如:
void* handle = dlopen("libmath.so", RTLD_NOW);
if(!handle){
fprintf(stderr, "dlopen:%s\n", dlerror());
exit(EXIT_FAILURE);
}
-
辅助工具
查看符号表:nm
列出目标文件、可执行程序、静态库或共享库中的符号
例: nm libmath.a
查看依赖:ldd
查看可执行文件或者共享库所依赖的共享库
例: ldd a.out