1.什么是静态库和动态库
在Linux操作系统中,普遍使用ELF格式作为可执行程序或者程序生成过程中的中间格式。ELF(Executable and Linking Format,可执行连接格式)是UNIX系统实验室(USL)作为应用程序二进制接口(Application BinaryInterface,ABI)而开发和发布的。工具接口标准委员会(TIS)选择了正在发展中的ELF标准作为工作在32位Intel体系上不同操作系统之间可移植的二进制文件格式。而在windows下是PE(Portable Executable,可移植可执行)。
而通常目标文件有三种形式:
- 可执行目标文件。即我们通常所认识的,可直接运行的二进制文件。
- 可重定位目标文件。包含了二进制的代码和数据,可以与其他可重定位目标文件合并,并创建一个可执行目标文件。
- 共享目标文件。它是一种在加载或者运行时进行链接的特殊可重定位目标文件。
1.1静态库
前面所提到可重定位目标文件以一种特定的方式打包成一个单独的文件,并且在链接生成可执行文件时,从这个单独的文件中“拷贝”它自己需要的内容到最终的可执行文件中。这个单独的文件,称为静态库。linux中通常以.a(archive)为后缀。
应用:当程序运行对于空间要求较低,二而对间要求较高时。例如:启动进程、数据库(mysql)
1.2动态库
动态库和静态库类似,但是它并不在链接时将需要的二进制代码都“拷贝”到可执行文件中,而是仅仅“拷贝”一些重定位和符号表信息,这些信息可以在程序运行时完成真正的链接过程。linux中通常以.so(shared object)作为后缀。
应用:当程序运行对于时间要求较低,二而空间要求较高时。
2.静态库的创建及使用(c++用g++)
创建静态库,或者将目标代码加入到已经存在的静态库中,可以使用命令:
- 将将 .c 生成 .o 文件
gcc -c add.c -o add.o
- 使用 ar 工具制作静态库
ar rcs lib库名.a add.o sub.o div.o
- 编译静态库到可执行文件中:
gcc test.c lib库名.a -o a.out
首先需要创建实现加减乘除等的源码(即.cpp)文件,这是用来生成.o文件的,接下来就可以用利用ar工具完成静态库的制作,然后在主程序(main.cpp)中链接静态库。将静态库编译到可执行文件中。
3.动态库的创建与使用
创建步骤:
- 将 .c 生成 .o 文件(生成与位置无关的代码 借助 -fPIC)
gcc -c add.c -o add.o -fPIC
- 使用 gcc-shared 制作动态库
gcc -shared lib库名.so add.o sub.o div.o
- 编译可执行程序时,指定所使用的动态库 -l: 指定库名 -L :指定库路径。
gcc test.c -o a.out -lmymath -L 后跟路径
- 运行可执行文件 ./a.out
补充:
运行可执行文件 ./a.out 时出错原因
原因:
连接器:工作于连接阶段 工作时需要 -l 和 -L
动态链接器:工作与程序运行阶段 工作时需要提供动态库所在目录位置(通过环境变量解决 export LD_LIBRARY_PATH=动态库路径 ./a.out)
解决方法:
【1】临时生效:终端关闭环境变量即失效。
【2】永久生效:写入终端配置文件。 .bashrc 建议使用绝对路径。
1) vi ~/.bashrc
2) 写入 export LD_LIBRARY_PATH=动态库路径 保存
3). .bashrc/ source .bashrc / 重启 终端 —> 让修改后的.bashrc生效
4)./a.out 成功!!!
【3】拷贝自定义动态库到/lib(标准C库所在目录位置)(不推荐)
【4】配置文件法
1)sudo vi /etc/ld.so.conf
2) 写入动态库绝对路径 保存
3)sudo ldconfig -v 使配置文件生效。
4)./a.out 成功!!!— 使用 ldd a.out 查看
4.静态库和动态库(共享库)的区别
- 静态库被程序静态链接于编译时,而共享库被动态链接于运行时;
- 静态链接时,需要把所有对静态库的引用内容都嵌入到最终的可执行文件中,且相同模块并不共用,都有相应的副本,因此相应的可执行文件在磁盘和内存中所占空间较大;而动态链接是发生在运行时的,并且是共享的,因此相应的可执行文件在磁盘中所占空间较小;
- 由于静态链接是在编译时完成的,因此可执行文件中以及包含有所需的静态库,可执行文件可以单独运行;由于动态链接是在程序运行时完成的,可执行文件在加载入内存运行时才会链接共享库,因此可执行文件必需共享库的支持,不能单独运行;
- 当静态库中某个模块更新后,需要重新编译链接生成相应的可执行文件;另一方面若共享库中某个模块更新了,只要接口没有改变,就不需要重新编译链接生成可执行文件;
- 静态链接比动态链接速度稍快
- 静态库中不能包含共享库,而共享库中可以包含静态库
- 综合以上区别,可以发现动态链接的性能是明显优于静态链接的,但是这不一定就说明静态链接一定比不上动态链接了。如果库本身就比较小且不经常改变,基于速度的角度,应当选择静态链接,否则还是应当选择动态链接,由于是大型软件需要经常维护、扩展之类的情况。除此之外,静态链接的一个显著优点是其相应的可执行文件已经是完整的,包含所有所需的模块,因此可以很方便地移动到其他地方执行。