linux中库的类型
静态库:编译链接时已加入程序中。如:libxxx.a
动态库:编译链接时记录符号未加入程序,在程序运行时调用。如:libxxx.so
关于如何生成库文件(源文件print_1.c print_2.c)
1.静态库的生成:
gcc -O -Wall -c print_1.c print_2.c
ar -rsv libmy_print.a print_1.o print_2.o
注:查看 libmy_print.a中的.o文件 ar -t libmy_print.a
2.动态库的生成:
gcc -fPIC -shared -o libmy_print.so print_1.c print_2.c
-fPIC 使输出的对象模块是按照可重定位地址方式生成的.(Position Independent Code 位置无关代码)
-shared 指定把对应的源文件生成对应的动态链接库文件 libmy_print.so文件。
注:ldd 是用来查看链接了那些动态链接库
关于如何链接库文件(main.c)
1.链接动态库文件
gcc -o main_so main.c -L. -lmy_print
注:编译器会优先链接动态库,如果没有动态库就链接静态库
2.链接静态库文件
gcc -o main_a main.c ./libtestlib.a
(gcc -o main_a main.c -L. -lmy_print -static)
注:第二种链接方式(加-static)生成的程序完全不需要支撑库,第一种方式生成的程序不需要libmy_print.a(或libmy_print.so)但还是需要系统库。
相关环境变量和文件
linux默认的库查找目录为/lib和/usr/lib,如果使用的库文件在其他地方,程序运行时可能不能找到。可通过下面的方法使程序正确找到库文件。
LD_LIBRARY_PATH 共享库的搜索路径
LD_PRELOAD 优先使用该路径下库中的函数 (警惕该变量,慎用!)
/etc/ld.so.conf 可在文件中添加上库搜索路径
/etc/ld.so.conf.d 目录
/etc/ld.so.cache 用ldconfig生成的,strings命令查看
编译程序时使用-Wl,-rpath=$(prefix)/lib
gcc -o main_so main.c -L. -lmy_print -Wl,-rpath=./
动态库的调用
1.隐式调用
编译程序时:gcc -o main main.c -L. -lmy_print
执行程序时:设置好so库查找路径后(LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH)执行./main
2.显示调用
相关函数(头文件dlfcn.h)
函数名
|
功能描述
|
dlopen
|
打开对象文件,使其可被程序访问
|
dlsym
|
获取执行了 dlopen 函数的对象文件中的函数的地址
|
dlerror
|
该函数没有参数,它会在发生前面的错误时返回一个字符串,同时将其从内存中清空; 在没有错误发生时返回 NULL,
|
dlclose
|
关闭目标文件。如果无需再调用共享对象的话,应用程序可以调用该方法来通知操作系统不再需要句柄和对象引用了。它完全是按引用来计数的,所以同一个共享对象的多个用户相互间不会发生冲突(只要还有一个用户在使用它,它就会待在内存中)。任何通过已关闭的对象的 dlsym 解析的符号都将不再可用
|
函数示例:
-
//main.c 测试动态库显式调用的程序
-
//用于动态库管理的系统头文件
-
#include<dlfcn.h>
-
//要把函数的头文件包含进来,否则编译时会报错
-
#include "mylib.h"
-
int main(int argc,char* argv[])
-
{
-
//声明对应的函数的函数指针
-
void (*pTest)();
-
//加载动态库
-
void *pdlHandle = dlopen("libtest.so", RTLD_LAZY);
-
//错误处理
-
if(pdlHandle == NULL )
-
{
-
printf("Failed load library\n");
-
return -1;
-
}
-
char* pszErr = dlerror();
-
if(pszErr != NULL)
-
{
-
printf("%s\n", pszErr);
-
return -1;
-
}
-
//获取函数的地址
-
pTest = dlsym(pdlHandle, "test");
-
pszErr = dlerror();
-
if(pszErr != NULL)
-
{
-
printf("%s\n", pszErr);
-
dlclose(pdlHandle); return -1;
-
}
-
//实现函数调用
-
(*pTest)();
-
//程序结束时关闭动态库
-
dlclose(pdlHandle);
-
return 0;
-
}
使用-ldl选项指明生成的对象模块需要使用共享库 gcc -o main -ldl main.c
阅读(2394) | 评论(0) | 转发(1) |