2.动态库与静态库

本文详细介绍了库文件在编程中的作用,区分了静态库和动态库的概念,包括它们的链接方式、优缺点以及如何生成和使用。重点讲解了静态库的编译过程、动态库的制作流程,以及如何处理头文件和环境变量以确保程序正确执行。

1.库的制作

库文件是计算机上的一类文件,可以将库文件看做是一种代码仓库。它提供给使用者一些可以直接拿来用的变量,函数或类。库是一种特殊的程序,但是库是不能单独运行的。

库文件有两种:静态库和动态库

静态库: GCC进行链接时,会把静态库中代码打包到可执行程序中

动态库: GCC进行链接时,动态库的代码不会被打包到可执行程序中,程序启动之后,动态库会被动态加载到内存中,通过动态库地址访问动态库,但是对于自己刚刚写的库系统是不知道库的内存地址的,所以就要自己手动为动态库添加环境变量地址,通过ldd (list dynamic dependencies)命令检查动态库依赖关系

库的好处:1.代码保密(C++ 的反编译还原度非常低) 2.方便部署和分发

应用场景:比如Office软件的各个组成部分有相似的外观和功能,那么就可以调用同一个库文件中的函数生成那些组件

1.1 如何生成静态库

1.1.1 书写相关函数

1.文件如何保存

这里实现了一个算术运算的库,主要进行相关加减乘除操作,并根据命名规则将他们放在对应的目录下

image-20211030111747506

2.文件内容

(1)head.h

对函数进行声明

image-20211030112241751

(2)方法体的实现

add.c

image-20211030112339704

(3) main 执行方法实现

image-20211030112442437

1.1.1 静态库的命名规则

image-20211030105426907 image-20211030105510007

1.1.2 静态库的制作

(1)gcc -c 对库文件编译

gcc -c add.c mult.c sub.c div.c

报错,头文件找不到,使用 -I 将头文件导入

image-20211030112709156
gcc -c add.c mult.c sub.c div.c -I ../include

上面代码注意,不需要添加 head.h ,直接将文件 dictionary 添加进来即可。于是就生成了一堆 .o 文件

image-20211030113140520

(2)对 .o文件进行打包 ,成 .a 库文件

ar rcs libmath.a add.o div.o mult.o sub.o

(3)执行 main.c 方法

执行 main.c 方法,调用的库都是从 head 文件中查找的,所以还会报一个找不到 head.h 文件的情况。这时候将 head.h 再次导入

gcc  main.c -I include/ // 编译
image-20211030114005640

如上图所示,提示未引用库的 error ,这里需要使用 -L 参数将打包的库进行引用

gcc main.c -o app -I ./include/ -L ./lib/ -l math

注意:

-l 参数后的内容是和 -L 后面的文件对应的 .a 文件相关,调用的时候直接添加 lib 的名称即可

1.2 动态库的制作

这里是将上面的文件定义成动态库的方式

1.2.1 文件命名规则

image-20211030121941820

1.2.2 动态库的制作

1.gcc 得到 .o 文件,得到和位置无关的代码

gcc -c -fpic add.c div.c mult.c sub.c -I ../include/

参数:fpic 生成与位置无关的代码,原因是动态库与静态库不同,静态库是将静态库代码嵌套在可执行文件中。但是动态库的代码是放在内存的,是不确定位置的,所以就需要有这个参数

2.gcc 得到动态库

gcc -shared *.o -o libmath.so

*.o 就是将所有的 .o 文件聚合,注意这里别忘了加 .o 参数

shared 作用是生成一个共享库

image-20211030122540111

如上图所示就生成了一个 .so 的可执行文件

3.根据动态库生成可执行文件

gcc main.c -o main -I include/ -L lib/ -l math

但是如果执行这个可执行文件就发现报错,主要是找不到共享库的地址

image-20211030123155301

1.2.3 如何让程序找到共享库

image-20211030123245912
ldd main // 查看所用动态库
image-20211030123531107

查看电脑环境变量:

那么这样的话只需要将动态库的地址配置到环境变量中既可

env

其中 path 就是配置的环境信息

image-20211031223057671

1.2.4 在环境变量中声明动态库

为环境变量添加动态库(用户级别的配置)

用户级别配置是在 .bashrc 文件下配置的

编辑 .branch 文件,在最后添加动态库地址,最后再将这个文件编译一下

image-20211031224750386
source .bashrc   or  . .bashrc // 编译文件

source 的含义是读取并执行 source 后面文件;. 是 source 这个 operation 的简写。最后在执行 ldd main 就找到了这个库的地址,并且 main 这个文件也可以执行

image-20211031225123798

知识延伸:如何查看某个变量的值

上面使用 $+变量名获取变量值,用同样的方法再结合shell 指令就可以使用 ¥ 将这个值输出,看到这个变量中拼接的值

echo $LD_LIBRARY_PATH
image-20211031230234741

为环境变量添加动态库(系统级别的配置)

系统界别的配置主要是在 /etc/profile 文件中,所以就在这个文件下对这个变量添加动态库目录

sudo vim /etc/pro

使用和上面相同的添加动态库的指令,并在最后一行添加动态库地址,并且使用 source 进行编译

image-20211031230654338

最后在执行 main 方法就发现可以运行了

1.2.5 在文件列表中添加 PATH

通过 2.2.3 动态库的保存路径中获知可以直接修改 /etc/ld.so.cache 文件对动态库 path 进行调用。但是这个文件如果使用 vim 打开都是乱码,其实这个文件可以通过使用 conf 文件进行映射

sudo vim /etc/ld.so.conf

直接将地址粘贴到这个文件中即可

image-20211031232137699

然后使用 ldconfig 指令将动态库进行共享

sudo ldconfig

最后就可以直接对 main 文件执行

视频作者不太建议使用直接更改 lib 的方式更改库文件,因为 lib 中的文件太多,容易混乱

1.3 动态库和静态库的区别

1.3.1 制作流程上的差别

1.静态库的制作

image-20211101103923631

2.动态库的制作

image-20211101104000087

1.3.2 静态库的优缺点

1.静态库

优点缺点
静态库被打包到应用程序中加载速度快消耗系统资源,浪费内存
发布程序无序提供静态库,直接调用静态库当静态库中代码更新后,所以引用它的文件全部要进行相关喜欢,更新,部署,发布麻烦

2.动态库

优点缺点
可以实现进程间资源共享加载速度比静态库慢
相比于静态库,动态库更新部署发布简单发布程序是时需要提供依赖的库文件
可以控制何时加载动态库
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值