静态库和动态库浅析
前言
静态库和动态库技术在目前应用广泛,他们都很重要,不同的应用场景需要不同的技术,有的地方适合用静态库,而有的地方需要使用动态库技术,所以了解两者的区别和优缺点,知道什么时候该用哪一种技术就显得很重要。
一、什么是库
库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
库有两种:静态库(.a、.lib)和动态库(.so、.dll)。在Linux下,静态库后缀为.a,动态库后缀为.so。
由于目前在学有关Linux方面的知识,所以本文所讲的库都是基于Linux的,其实windows下的库也是大同小异。以上是本人结合所学后的一点小看法,这篇博客作为我的第一篇博客,由于小白能力有限,大神勿喷哈哈!如果有错误欢迎指出!
二、静态库
静态库是一些目标文件(后缀名为.o)的集合,是一种可执行的二进制程序文件
,当需要使用到某个静态库时,在链接的时候要将自己所生成的那些目标文件和引用到的静态库链接到一起生成一个可执行文件,即会将静态库复制到你的目标文件然后生成一个可执行文件。对应的链接方式称为静态链接。
三、动态库
动态库是一种不可执行的二进制程序文件
,当需要使用到某个动态库时,在链接的时候不需要将动态库复制到你的目标代码中,而是在你的程序运行的时候需要用到动态库的内容时才将动态库载入到内存,而且如果此时有多个程序用到同一个动态库的内容,此时内存只需要有一份该动态库的副本即可,所有用到该动态库的程序共享这个副本。对应的链接方式称为动态链接。
四、静态库优缺点
优点:静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系,便于移植。
缺点:
- 直接复制到目标程序会使我们的程序变得非常的臃肿,会很浪费我们的磁盘和内存资源(运行时)。如:运行时,在内存中不同的程序如果要使用同一份静态库的时候,每个程序都需要复制一份静态库到自己的程序中,非常的占用内存。
- 当需要更新某个静态库的时候,使用到该静态库的程序需要整个重新进行链接生成。
五、动态库优点
- 动态库在程序运行时由系统动态加载到内存中供程序调用。使用动态库的优点是系统只需载入一次动态库,不同的程序可以得到内存中相同的动态库的副本,因此节省了很多内存。
- 当需要对动态库进行更新时,无需将整个程序进行重新生成,只需要单独对需要更新的动态库进行更新,当重新运行你的程序的时候,在动态链接的时候就会把已经更新的动态库进行链接。
六、静态库的创建和使用
1、创建
- 首先,编写.c文件,然后通过预处理、编译、汇编生成一组目标文件
- 然后通过下面的打包指令将目标文件打包成静态库文件(.a)
ar src libmymath.a add.o sub.o div1.o mul.o
这里的ar是打包工具,src 是跟随的参数
libmymath.a是打包后的静态库名,格式为:lib库名.a
后面是一组目标文件
一点习惯1
2、使用
gcc test.c -o test -l./lib/mymath -I ./inc
注意使用的时候静态库要去掉前缀lib和后缀.a(静态链接的时候就不能去掉)
test.c是你的程序
-l./lib/libmymath.a指定静态库所在的目录
-I ./inc 指定静态库头文件所在的目录
七、动态库的创建和使用
1、创建
- 首先,将.c文件生成.o文件,此过程需要生成与位置无关的代码(使用-fPIC参数),命令如下:
gcc -c add.c -o add.o -fPIC
gcc -c sub.c -o sub.o -fPIC
gcc -c div.c -o div.o -fPIC
- 使用 gcc -shared 制作动态库
gcc -o -shared lib库名.so add.o sub.o div.o
2、使用
- 编译生成可执行程序
gcc test.c -o a.out -lmymath -L./lib -I./inc
注意使用的时候动态库要去掉前缀lib和后缀.so(动态链接的时候就不能去掉)
这里的 -l指定动态库名 -L指定动态库路径 -I指定动态库头文件
- 最后运行 ./a.out,但是会出错!!!
原因。2
- 解决方案:
- 通过环境变量:
export LD_LIBRARY_PATH=动态库路径
但是这样有个缺点,就是重启终端后再次执行./a.out还是会报错,这是因为,环境变量是进程的概念,你设置的变量是在当前终端进程下设置的,也就是只在当前终端有效,当你新创建一个终端的时候,相当于运行了一个新的进程,此时该进程读取的环境变量是新创建进程的默认环境变量,而不是你之前新设置的那个环境变量了。
- 永久生效:写入 终端配置文件 ~/.bashrc
写入 export LD_LIBRARY_PATH=动态库路径 (建议使用绝对路径),修改后记得要让修改后的~/.bashrc 生效,生效方法:(1). .bashrc/ (2) source .bashrc/ (3)重启终端 - 拷贝 自定义动态库到 /lib(标准C库所在的目录位置,这样当进行动态链接的时候动态链接器会到这个目录去找寻找你的动态链接库)
- 配置 /etc/ld.so.conf文件
1)sudo vim /etc/ld.so.conf
2)写入动态库绝对路径 然后保存
3)sudo ldconfig -v 使配置文件生效
注:可以使用 ldd a.out 查看此可执行程序的动态链接库所链接的目录,如果没有链接到所需的动态库路径,就会显示 没有找到文件。