认识动静态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静
态库
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文
件的整个机器码
在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个
过程称为动态链接(dynamic linking)
动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚
拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间
库的本质:一堆.o文件的集合。
库的名称:以libc.so为例,去掉前缀lib 去掉后缀.so ,留下的就是库的名称
生成静态库
将add.c、sub.c生成add.o和sub.o,然后进行打包生成静态库
将头文件和生成的静态库分别放在mylib目录下的include目录和lib目录下
生成静态库的语法格式
ar -rc 生成的静态库名称,想要打包的.o文件
上述过程在makefile文件中操作:
模拟使用静态库:
.h文件就是库中函数的声明相当于告诉使用者库中都有什么接口,.o文件中有这些函数的实现,所以对于使用者来说使用第三方库时包含第三方库的头文件和指明库即可。这里模拟实现使用者下载并使用第三方库是将当前路径下的库文件复制到上级目录实现的。
使用静态库并生成可执行程序:
其中-I后面跟的是头文件所在的路径,-L后面跟的是静态库所在的路径,-l后面跟的是静态库的名称
静态库链接的过程:
生成动态库
动态库的生成方法:一是在生成.o文件时需要加上fPIC生成位置无关码。二是在打包时候使用gcc命令,加上shared,表示生成共享库格式。
手动打包.h文件和.so文件复制到上级目录,模拟动态库的发布与下载。
尝试使用动态库编译并运行程序:
编译没有问题但是运行时报错:找不到动态库。原因是编译时我们告诉了gcc编译器在哪里链接动态库和要连接的动态库的名称,但是运行可执行文件是操作系统将该文件加载到内存中变成一个进程,动态库是动态链接的,在程序运行时才去链接动态库,但是并没有告诉操作系统动态库在哪里所以报错。
解决方法
1.将第三方库的头文件放到系统的头文件路径下,将第三方库放到系统库的路径下,但是在使用库时还是要指明库的名称
cp mylib/include/*.h /usr/include/
cp mylib/lib/*.so /lib/
2.在环境变量中添加第三方库
$LD_LIBRARY_PATH //OS在动态链接的时候会在这个环境变量下寻找动态库的路径,然后找到动库
echo $LD_LIBRARY_PATH //查看当前环境变量中存储的动态库的路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/kk/mylib/lib
添加到环境变量中的第三方库的路径只在本次登录虚拟机期间有效,下次登录使用时还得重新添加。
3.在配置文件中设置
/etc/ld.so.conf.d/ OS在链接动态库时会这个路径下的配置文件中查找第三方库的路径
添加配置文件的步骤:
1.cd /etc/ld.so.conf.d
2.touch kuname.conf
3.vim kuname.conf
4.将动态库的路径写入该文件
5.ldconfing //相当于刷新一下当前路径下的所有配置文件
动态库的加载:
可执行程序使用到动态库中的实现方法,在可执行程序中记录了该实现方法在库中的偏移量,在运行时OS将动态库加载到内存,通过页表映射到虚拟内存中的共享区,此时库就有了地址,偏移量根据库的地址就能计算出要使用的函数等实现方法的地址,就可以找到所需要的方法。偏移量是在生成动态库时使用用的-fPIC生成的与位置无关码。动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。