动态库和静态库

区别

假设库的大小是500M
静态库的时候,是把库都编译进程序中,每一个程序就多一个500M,因为实在自己程序里,所以调用的时候速度快
动态库是所有程序共享这个一个库,动态库会先保存在内存中,程序需要的时候会调用,比在自己的代码里多了一个进入内存的操作,所以速度比静态库慢

  • 静态库适用于对空间需求低,速度需求高的场景,比如操作系统的启动
  • 动态库适用于对空间要求高,时间要求低的场景,比如数据库

静态库的制作和使用

静态库制作代码

ar rcs libmylib.a file.o

前两个命令是固定的,第二个c是不存在就创建的意思,第三个是制作的静态库的名字,第四个是输出文件
注意:静态库的名字必须以lib开头,mylib为自己的名字,.a为后缀
例子:
首先建立一个add.c, sub.c, div1.c
image
输出.o文件记得加-c
image
image
再移动一下
image
再也一个测试文件
image
注意:编译时候的错误会出现行号,没有出现行号是链接时候的错误
image
image
如下图可知,编译出来的文件比较大
image
gcc的时候,注意.c文件在前,静态库在后
注意上面有警告,隐式声明,出现在编译阶段。当没有函数定义或没有函数声明的情况下,编译器会作隐式声明。但是编译器一般只会声明 int 函数名(int, int )这种,出现void * 函数名的时候就不行了,容易出现错误
上述问题解决办法就是在test.c中隐式声明三个函数:
int add(int, int)
int sub(int, int)
int div1(int, int)
再但是:
上面操作是我自己做的静态库,在网上下的时候,并不知道函数名字,所以一般静态库制作者会再制作一个头文件声明这些函数,在使用的时候调用头文件即可。
image

image

动态库的制作和使用

第一步同静态库,也是将.c文件生成.o文件。(生成与位置无关的代码
注意:动态库里面的函数,只有当调用程序执行到动态库的函数位置上时才会调用动态库,即调用的动态库的函数地址是动态在变的,因为动态库在变
地址回填:
image
动态库的函数在没调用之前是没有地址的,使用反汇编
objdump -dS test > out
image
由图可知,是根军@plt来绑定地址的。

  1. 所以生成动态库的时候使用
gcc -c add.c -o add.o -fPIC

这样生成的add里面的函数都是plt地址的
2. 再使用

gcc -shared -o lib名字.so add.o sub.o div1.o

制作动态库
3. 使用动态库:编译可执行文件时要指定动态库
-l, 用来指定库名
-L, 用来指定库路径

gcc test.c -o test.out -l mylib -L ./lib

注意使用的时候要去掉lib和.so
image

image
如图所示出错了。
出错原因:
链接器: 工作与链接阶段,在a.out文件执行前,工作的时候需要l和L
动态链接器: 工作在程序运行阶段,需要提供程序动态链接库所在位置,如果没有提供,就会去LD_LIBRARY_PATH的环境变量找
image
但是环境变量是进程的概念,用export之后,打开新的进程就没了。永久生效~./bashrc,更改,然后source 它或者. 执行或者重启,建议使用永久路径
第三种方法,也可以直接复制到./lib下
ldd a.out: 查看可执行文件的动态库路径
第四种方法,vim /etc/ld.so.conf
加入动态库路径,再输入 sudo ldconfig -v加载一下

数据段合并

image
链接的时候会合并代码段和制度数据段,合并的好处是为了节省空间, 通过MMU映射,4kb是一页(磁盘是512k),这两段比较小,用不了8k,所以合并。
。bss和.data也会合并

posted @ 2022-02-18 20:54  蘑菇王国大聪明  阅读(147)  评论(0编辑  收藏  举报