【Linux】静态库与动态库

静态库与动态库(共享库)

首先我们来看一下静态链接与动态链接

1)静态链接

由链接器在链接时将库的内容加入到可执行的程序中去

一个代码文件原本是10k大小,它通过静态链接调用了一个大小为10k的静态库,那么编译后文件的大小会变为20k

我们可以这么理解,静态链接相当于库文件的内容被嵌到文件中一同编译

这么说,如果一个静态库大小为1M,有1024个文件调用了这个静态库
那么相比于使用共享库我们会少了1GB大小的内存空间

优点:

  • 对运行的环境依赖性小,具有较好的兼容性
  • 运行的效率更高

缺点:

  • 生成的程序比较大,需要更多的系统资源,装入内存时会消耗更多的时间
  • 库函数更新后,必须重新编译应用程序

~

2)动态链接

连接器在链接的时候仅仅建立与所需库函数之间的链接关系

在程序运行时,要使用对应的函数了,这时候才将所需的资源调入可执行程序(这个时候函数才被加载到内存,也就是此时动态库函数的地址才会被绑定)

优点:

  • 在需要的时候才调入资源函数
  • 简化程序的升级;有着较小的体积
  • 实现程序之间的资源共享(避免重复拷贝)

缺点:

  • 依赖动态库,不能够独立运行
  • 动态库版本问题严重

~

静态库的制作与使用

命名三部分:前缀lib + 库名 + 后缀 .a

步骤1:把c的源文件生成为对应的.o文件

#以add.c sub.c作为例子
# -c 只进行预处理和编译
# -o 指定生成的文件
gcc -c add.c -o add.o
gcc -c sub.c -o sub.o

步骤2:用打包工具ar将准备好的.o文件打包为.a文件

ar -rcs libtest.a add.o sub.o    
  • -r 更新
  • -c 创建
  • -s 建立索引

步骤3:编译生成可执行文件

  • -L : 表示要连接的库所在的目录
  • -l (小写L) :指定链接时所需要的库的库名(注意库名是去掉前后缀的部分)
  • -I (大写i) : 指定头文件路径
#测试文件为test.c,静态库libtest.a,头文件head.h
gcc test.c -I ./ -L ./ -l test -o test01  #-o 后面指定输出的文件

静态库制作完成后要将.a文件和头文件一起发布给用户

如果我们只有.a文件没有头文件,那我们编译文件,编译器找不到函数的声明,它根本不知道这个函数是从哪来的,自然也就出问题了

~

动态库的制作与使用

命名三部分:前缀lib + 库名 + 后缀 .so

步骤1:生成目标文件,此时要加编译选项 -fPIC
-fPIC 创建与地址无关的编译程序,是为了可以在多个文件中共享

gcc -c add.c -o add.o -fPIC

步骤2:生成共享库,此时需要加链接器选项 -shared
-shared 生成动态链接库

gcc -shared add.o sub.o -o libtest.so

步骤3:编译可执行程序时,指定所使用的动态库

  • -L : 表示要连接的库所在的目录
  • -l (小写L) :指定链接时所需要的库的库名(注意库名是指去掉lib前缀以及.so后缀的部分)
  • -I (大写i) : 指定头文件路径
#这里测试的文件为test.c ,使用的动态库为libtest.so
gcc test.c -o a.out -L ./ -l test -I ./

到了这里,我们去执行可执行文件./a.out,会报错说找不到共享库

那么为何我们这里已经用-L-l指定了动态库,它仍报错说找不到动态库呢?

这里涉及到链接器动态链接器的区别(虽然听着很像,但是他们完全不是一个东西):

  • 链接器:工作于链接阶段,工作时需要-L-l
  • 动态链接器:工作于程序运行阶段,工作需要提供动态库所在目录位置

每一次要去找动态库的时候,动态链接器都会去固定的地点找,如果它找不到,那么它就会报错说找不到动态库

~

那么如何让它找到动态库?

1)临时设置

刚刚我们说动态链接器回去固定的地方找动态库所在的地方,这个固定的地方就是环境变量LD_LIBRARY_PATH

这是一个专门服务于动态链接器的环境变量

那么也就是说,我们只需要设置环境变量并且让这条环境变量生效即可

export LD_LIBRARY_PATH=库绝对路径

😔 但是这个时候,我们如果把终端关闭,重新打开一个新的终端,这个时候再次执行同一个文件会再次报错找不到动态库

这是因为环境变量是对于一个继承来说的,我们刚刚设置的环境变量存在于刚刚的终端进程中,我们把终端关闭了,它也就无了

这时我们新打开的终端,又是默认的环境变量值

~

2)永久设置

😉那如果我们想永久生效的话,我们就要去修改一下终端的配置文件.bashrc

vi ~/.bashrc打开这个在家目录下的配置文件

在对应的位置更改这个固定的地点(改成你的动态库的绝对路径)就好啦

export LD_LIBRARY_PATH=库绝对路径

最后使环境变量生效 source ~/.bashrc

😄我是旺仔,和你一起成长

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值