今天我们来了解一下库文件,主要有以下几个内容:
一、库文件概念
- 概念 :通俗来讲就是将用户写好的程序打包成一个整体,当其他模块或用户使用时,只需要有这个库文件就可以了,不需要源代码文件。也可以理解为一组预先编译好的方法的集合。
- 存储位置:
- Linux系统存储库的位置一般在/lib或/usr/lib,在64位的系统上有些库也有可能被存储在/usr/lib64下。所以运行程序没有手动指定位置时,会在这几个默认的位置去找。
- 库的头文件一般在/usr/include下或其子目录。这也是为啥我们好多头文件是# include<xxxx.h>的原因。
- 库的分类:我们一般以扩展名进行区分
系统 | 静态库 | 动态库 |
---|---|---|
windows | .lib | .dll |
Linux | .a | .so |
- 特点: 函数方法声明在.h头文件中,函数实现在库中,库无法查看,因为不是源代码,而是经过经过编译链接后的一个文件。所以其他人无法看到我们的源代码,但可以通过.h文件调函数接口。
- 常用的库:C库:libc.so;C++库:libstdc++.so
二、静态库
首先我们学习静态库是如何生成和使用的。
(一)生成&&使用
1. 生成:两步
(1)利用gcc将所有源代码(.c)编译成中间文件(.o)
如
gcc -c *.c
注意此时的源代码不包含main.c,因为你要被他人使用,不能占用函数入口。
(2)使用命令生成库:
ar crv libxxxx.a 所有的中间文件
c是创建库,r是将方法添加到库,v是显示过程,xxxx代表库的名字。
两步之后就会生成xxxx的静态库。
2. 使用:
在编译时需要连接库地址和库名称:
gcc -o main main.c -L库路径 -l库名称
注意库地址是静态库在哪里存储的路径,如果没给就在默认的/lib和/usr/lib下找;库名称是xxxx,不包括lib。
(二) 示例
我们来举个例子吧,用加减乘除四个函数的.c文件生成myMath.a静态库。
- 生成
(1)把四个.c文件都变为.o文件:
(2)生成静态库myMath.a
- 使用
然后开始使用:
(三) 特点
程序链接过程中,会从库中得到所需库的代码,复制到生成的可执行文件中,因此,静态库是在程序的链接阶段被复制到程序当中,和程序执行过程没有关系。
三、动态库
动态库我们有时也称为共享库,我们可以通过命令:
ldd main
查看main函数使用了哪写共享库。
(一)生成&&使用
- 生成
它的生成只有一步,借助gcc即可完成,所以也有人说它是一个不可单独执行的可执行文件,因为没有main,所以不可单独执行。生成命令:
gcc -shared -fPIC -o libxxxx.so 所有代码的源文件
源文件自然也不包含main.c。
- 使用:
和静态库的使用指令一样:
gcc -o main main.c -L库路径 -l库名称
但是运行会报错.
原因: 首先我们要明确它的生成没有问题,在运行时出错了,这和它的机制有关系,它不像静态库把代码直接复制过去,它只是在main函数中做了个标记,在运行时,系统根据这个标记找到库函数,进行运行。那么我们就可以看到我们的错误就是:只给mian函数指明了动态库的位置,但没给系统指出动态库的位置,系统在默认下找不到,自然就出错了,故总结共享库在程序运行时,由操作系统单独加载执行,不是和主函数一起的,所以在使用时也要告诉操作系统动态库的位置。那我们现在给系统指明路径如果多个共享库地址,用”;"分开,有两种办法:
(1)把动态库放到默认的两个路径/lib或/usr/lib下。通过指令mv即可实现。
(2)通过给环境变量LD_LIBRARY_PATH赋值(当前路径)给系统指明,但要注意,这个变量仅仅对当前终端有效,若想要永久修改,需要以管理员身份在家目录的.basgrc中添加这个变量并赋值。路径不包含中文。
添加环境变量:
export LD_LIBRARY_PATH=动态库绝对路径
查看变量值:
echo $LD_LIBRARY_PATH
(二) 示例
-
生成:
-
使用:
先删除上一个静态库生成的main,再进行使用:
我们可以看到在编译链接时没问题,运行时出错了,这时我们两种办法,在这我使用第二种添加环境变量:先pwd看一下动态路径在哪里,然后添加即可,我采用临时的环境变量:
(三) 特点
动态库在编译连接时只是在main函数中做个标记,告诉它地址,在运行时才会顺着地址找过来动态加载,所以在main运行时动态库必须存在,否则出错。
四、区别
那么我们来总结以下这两个库的区别:
- 静态库在链接时将用到的方法包含到最终生成的可执行文件中,而共享库不包含,只做标记,在运行时,才动态加载。
- 动态库占用空间小,有共享的特点。假如静态库10个人用,那么10个人每个人一份,就有10份;而动态库每个做个标记,运行时动态加载即可,始终一份。
- 动态库适用于更新操作。如果库功能修改更新,那么静态库需要重新链接才可以使用;动态库就不用,因为它只是给了标记,在运行时动态加载,肯定是最新的库。
- 动态库这么好,那么在静态库动态库名称一样时优先使用动态库。
加油哦!💪。