Linux库文件---静态库和动态库

静态库和动态库

静态库:
在生成可执行文件的时候载入库。因此生成的可执行文件较大。但是在运行时候就不再需要库了。

  1. 生成目标文件
gcc -c fun.c -o fun.o
  1. 生成静态库,以lib开头,加库名,.a 为后缀,表示Archive。
ar crs libfun.a fun.o

ar命令类似于tar命令,起一个打包的作用,但是把目标文件打包成静态库只能用ar命令而不能用tar命令。选项r表示将后面的文件列表添加到文件包,如果文件包不存在就创建它,如果文件包中已有同名文件就替换成新的。s是专用于生成静态库的,表示为静态库创建索引,这个索引被链接器使用。ranlib命令也可以为静态库创建索引,以上命令等价于:

ar r libfun.a fun.o
ranlib libfun.a
  1. 库的使用
gcc main.c -o main -L . -lfun

-L 表示链接库的路径,选项告诉编译器去哪里找需要的库文件,
-L . 表示在当前目录找,注意,即使库文件就在当前目录,编译器默认也不会去找的,所以该选项不能少。
-Ifun 告诉编译器需要链接libfun库(-l是小写的l)
-I(大写的i) 选项告诉编译器去哪里找头文件
编译器默认会找的目录可以用 -print-search-dirs 选项查看

gcc -print-search-dirs

在这里插入图片描述

//fun.c
int add(int a,int b){
	return a+b;
}
//main.c
#include<stdio.h>
extern int add(int a,int b);
int main(void){
	printf("%d\n",add(1,2));
	return 0;
}

在这里插入图片描述
在这里插入图片描述

动态库(共享库):
在执行可执行文件时需要链接库,因此可执行文件较小,但是在移植过程中需要连同库一起移植

  1. 生成目标文件
gcc -fPIC -Wall -c fun.c -o fun.o
  1. 生成共享库 共享库 lib + 库名 .so
gcc -shared fun.o -o libfun.so
  1. 库的使用
gcc main.c -o main -L . -lfun

动态库的加载

  1. 将库文件放在 /lib 或者 /usr/lib
  2. 修改环境变量LD_LIBRARY_PATH 增加我们库的路径

在这里插入图片描述
执行时出现,下面错误:
在这里插入图片描述
那怎么解决呢?我们先使用ldd 命令看main,发现没有找到动态库,那好吧,我们还是吧动态库复制到/usr/lib/目录下,然后在用ldd main看看,结果时找到了,然后执行main,就出现了结果为3.
在这里插入图片描述

ldd模拟运行一遍main,在运行过程中做动态链接,从而得知这个可执行文件依赖于哪些共享库,每个共享库都在什么路径下,加载到进程地址空间的什么地址。
/lib64/ld-linux-x86_64.so.2(0x00007f5c0beee000)是动态链接器,它的路径是在编译链接时指定的,gcc在做连接时用 -dynamic-linker指定动态链接器的路径,它也像其它共享库一样加载到进程的地址空间中。
libc.so.6的路径/lib/x86_64-linux-gun/libc.so.6是由动态链接器ld-linux.so.2在做动态链接时搜索到的
libfun.so的路径没有找到。
linux-vdso.so.1这个共享库其实并不存在于文件系统中,它是由内核虚拟出来的共享库,所以它没有对应的路径,它负责处理系统调用。所以总之,共享库的搜索路径由动态链接器决定,从ld.so(8)的Main Page可以查到共享库路径的搜索顺序:
1.首先在环境变量LD_LIBRARY_PATH所记录的路径中查找
2.然后从缓存文件//etc/ld.so.cache中查找。这个缓存文件由ldconfig命令读取配置文件/etc/ld/so/conf之后生成。
3.如果上述步骤都找不到,则到默认的系统路径中查找,先是/usr/lib然后是/lib,也可以把生成的共享库文件拷贝到/usr/lib或者/lib下面,这样可以确保动态链接器能找到这个共享库。
4.在编译可执行文件main的时候就把libfun.so的路径写死在可执行文件中:
gcc main.c -g -L. -lfun -Ifun -o main -Wl,-rpath,/mnt/hgfs/share
-Wl,-rpath,/mnt/hgfs/share表示 -rpath /mnt/hgfs/share是由gcc传递给链接器的选项。

我们可以看到readelf的结果多了一条rapth记录:
在这里插入图片描述在图片中我们可以看出,可执行文件运行时需要哪些共享库也都记录在.dynamic段中。当然rpath这种办法也不是很推荐,把共享库的路径定死了,失去了灵活性。

接下来看看第2中方法:
在这里插入图片描述把libstack.so所在目录的绝对路径(比如/mnt/hgfs/share)添加到/etc/ld.so.conf中(该文件中每个路径占一行),然后运行ldconfig:
在这里插入图片描述
运行 ldconfig -v
在这里插入图片描述
在这里插入图片描述该方法也是较常用的方法。

链接共享库和链接静态库有什么区别呢?
在链接libc共享库时只是指定了动态链接器和该程序所需要的库文件,并没有真的做链接,可执行文件main中调用的libc库函数仍然是未定义符号,要在运行时做动态链接。而在链接静态库时,链接器会把静态库中的目标文件取出来和可执行文件真正链接在一起。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值