动静态库的概念
- 静态库: Linux下,以.a为后缀的文件。程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。本质是在编译时把静态库中的代码(不是一次性加载,而是分页加载)复制到了进程的的代码区中。
- 动态库: Linux下,以.so为后缀的文件。程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
- 静态链接: 将库中的相关代码复制进可执行程序中的过程。
- 动态链接: 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中。
- 链接的本质: 链接.o文件和.lib文件
- 库文件名称: 比如libc.so,去掉前缀lib和后缀.so,剩下的就是库名
实例演示:
分别使用静态链接和动态链接编译生成两个可执行程序,比较两个程序的大小
使用gcc静态链接编译时,命令要带上**-static** 选项,如下:
如果报错可以执行如下指令:yum install glibc-static
可以用file命令去查看文件链接属性
可以使用ldd命令查看可执行程序的依赖库,动态链接生成的可执行程序才有依赖库,静态链接升序的可执行程序不依赖任何库文件,因为库文件的代码已经复制进可执行程序了
总结动静态库的优缺点:
静态库
- 优点: 程序运行的时候将不再需要静态库
- 缺点: 生成的可执行程序比较大。如果多个使用静态链接生成的程序同时运行会占用大量的内存空间
动态库
- 优点: 动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间
- 缺点: 程序运行的时候依赖动态库
静态库的打包和使用
**静态库打包:**本质其实就是将代码编译成.o的二进制文件,然后进行打包
有以下4个文件add.c,add.h,sub.c,sub.h
打包静态库的步骤:
1.先将add.c和sub.c生成对应的二进制文件
2.使用ar归档工具对两个二进制文件进行打包,同时带上选项rc(rc分别代表replace和create),这里库名是mymath(前缀是lib,后缀是.a)
ar -rc libmymath.a *.o
3.上面两个步骤其实就把静态库打包好了,下面就是发布静态库———把头文件和静态库组织起来,头文件放在include下
上述的所有步骤也可以写进makefile里面,利用make指令一键打包和make output发布
libmymath.a:add.o sub.o
ar -rc $@ $^
add.o:add.c
gcc -c add.c -o add.o
sub.o:sub.c
gcc -c sub.c -o sub.o
.PHONY:output
output:
mkdir -p mylib/include
mkdir -p mylib/my_lib
cp -f *.a mylib/my_lib
cp -f *.h mylib/include
.PHONY:clean
clean:
rm -f *.o *.a
打包拷贝到别的目录
然后解压
结论:所谓的安装就是拷贝
test目前下test.c内容为:
#include<stdio.h>
#include<add.h>
#include<sub.h>
int main()
{
int x=10;
int y=20;
printf("%d\n",my_add(x,y));
return 0;
}
执行需要打如下指令:
这三个选项的含义是:
- -L:指明库文件所在路径
- -I(大写i):指明头文件所在路径
- -l(小写L):指明库文件名,即mymath(去掉前缀lib和后缀.a)
但是这样打出来的话是动态链接
静态链接需要加上-static
动态库的打包和使用
1.先将add.c和sub.c生成对应的二进制文件,注意这里生成二进制文件要带上选项**-fPIC**(位置无关码)——即使用的是相对地址,非绝对地址
2.使用gcc带上选项**-shared(生成共享库格式)**对二进制文件进行打包
3.对动态库进行发布,也就是将库文件和头文件进行组织打包(和静态库一样)
我们继续拷贝到另一个目录下,继续做实验
此时对程序进行编译不会报错,但是执行的时候会报错,原因在于这些指令是告诉gcc,但是当编译完以后,和gcc没有关系了,程序运行起来,OS和Shell也要知道库在哪里,你的库没有在系统路径下,OS无法找到!
解决方法1(关闭终端无效):
系统除了在系统默认路径下搜索,也会在LD_LIBRARY_PATH环境变量下搜索,默认如下:
我们把环境变量导进去即
这种方法有一个缺点,就是关闭终端就没有了,因为环境变量表是一张内存级的表,如果想永久有效就要修改环境变量相关的配置文件(比较复杂)
解决方法2(永久有效):
动态库在搜索时,可以自己定义conf配置文件的方式来让OS找到动态库
我们只需要把路径写到自己定义的conf里面
运行发现还是不可以,原因是没有更新配置文件,我们需要sudo ldconfig
解决方法3(永久有效&&方便):
建立软链接,说明搜索动态库默认可以从当前路径下搜索