静态库、动态库比较与制作
静态库、动态库比较与制作
静态库与动态库比较
-
文件名:在unix中静态库一般以
.a
结尾,动态库一般以.so
结尾 -
静态库:静态库和源码一起被打包到最终的可执行文件(ELF),节约了编译时间,最后得到的可执行文件体积大,但是速度快
-
动态库:动态库不和源码一起被打包,执行到库函数时会去动态寻找调用动态库中的库函数,可执行文件体积小,但是速度慢(现在二者速度差异减少)
静态库
制作方法
要制作一个静态库,或将目标代码加入到已存在的静态库中,可以使用以下命令:
ar rcs libmylib.a file1.o
- 准备好源码对应的目标
.o
文件
- 制作静态库
ar rcs libmymath.a add.o div1.o sub.o
得到libmymath.a
静态库,一个ar架构的文件
如何使用
一般的,制作好的动态库必须与对应的头文件一起提供者给开发者
将目标代码与静态库一起编译到一起使用:
gcc main.c libmymath.a -o main
生成ELF文件正常使用,生成的文件大小相对较大:
动态库
上一节静态库的制作需要用若干
.o
文件,动态库由于在程序中被用到响应的库函数,才会被加载到内存,然后去寻址执行相应函数,因此动态库需要生成"与位置无关的代码"
地址回填
程序中要使用动态库中的函数,不能依赖main在做地址偏移,也就是上图中,如果func1和func2动态库的库函数,则无法找到相应的地址,因为执行的ELF文件,没有经过.o
->ELF的地址回填步骤,所以动态库需要生成与位置无关的代码,-fPIC
静态库与动态库函数反汇编比较——延迟绑定
objdump -dS ELF
查看反汇编
动态库加载到内存,@plt
被替换掉,动态库函数才会有地址——延迟绑定
动态库制作
生成与位置无关的代码—— -fPIC
制作.o
时,增加参数,-fPIC
gcc -c add.c add.o -fPIC
gcc -share 制作动态库.so
gcc -shared -o libmylib.so add.o sub.o div1.o
编译ELF时,指定所用的动态库 -l: 指定库名 -L: 指定库路径
gcc main.c -o main -lmymath -L./lib
动态库加载错误及解决办法
根据上一节的步骤,可以利用源码和动态库生成可执行文件,运行时会报下面的错误:
链接器:工作于链接阶段,工作时需要-l
-L
动态链接器:工作于程序运行阶段,工作时需要提供动态库所在目录位置
二者无关,非说有关系,那就是张三和张三丰的关系~
【加载错误原因/解决办法】
总之,动态库在工作时,动态链接器会去几个固定位置找.so
的位置:
-
环境变量:
export LD_LIBRARY_PATH=./lib
,环境变量只能使一个终端进程生效,临时办法 -
配置文件:
在home目录下的
.bashrc
中添加export LD_LIBRARY_PATH=lib的绝对路径
,然后source .bashrc
,非临时办法 -
把
xx.so
放到系统库目录下:/lib
,不建议这么做
【ldd
指令查看动态库依赖】
如果xx.so
加载失败,=>后面的动态库路径是空
- 修改
/etc/ld.so.conf
配置文件
【1】sudo vi /etc/ld.so.conf
,添加你的动态库路径
【2】sudo ldcofig -v
,更新查找动态块的路径
【3】测试是否好了