静态库与动态库详细剖析
技术交流QQ群:1027579432,欢迎你的加入!
1.库的介绍
- 库是什么?
- 二进制文件;
- 将源代码(.c或.cpp文件)变成二进制格式的源代码;
- 加密操作(只能使用,无法知道源代码是什么);
- 库制作出来后,如何给用户使用?
- 头文件(include文件夹中);
- 制作出来的库(lib文件夹中);
- 库的分类:
- 静态库:静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。.lib后缀(windows系统)、.a(Linux系统)
- 动态库:动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。.dll后缀(windows系统)、.so(Linux系统)
2.静态库的制作和使用
- 命名规则:libtest.a
- lib
- xxx:库的名字
- .a
- 制作步骤:
- 原材料:源代码.c或.cpp
- 将.c文件生成.o:gcc a.c b.c -c
- 将.o打包(archive):ar rcs 静态库的名字 原材料。例如:ar rcs libtest.a a.o b.o
- 将include(里面存放head.h文件)和lib文件夹(里面存放libtest.a文件)发送给程序的使用者即可。
- 静态库的使用:
- gcc 测试程序 -I 头文件路径 -L 指定静态库的路径 -l 静态库的名字 -o 可执行程序的名字.例如:gcc demo.c -I ./include/ -L ./lib/ -l mycalc -o app
- -L:指定静态库的路径
- -l:指定静态库的名字(去掉lib和.a)
3.动态库的制作和使用
- 命令规则:libxxx.so
- 制作步骤:
- 将源文件(.a和.c)生成.o:gcc a.c b.c -c -fpic(或fPIC)
- 打包:gcc -shared -o libxxx.so a.o b.o
- 动态库的使用:
- 头文件(例如:head.h)
- 动态库(例如:libtest.so)
- 参考头文件中的函数声明编写测试程序main.c
- gcc main.c -I ./include -L ./lib/ -l test -o demo
4.解决动态库加载失败的问题
- 对于elf格式(gcc编译后生成的可执行程序的文件格式)的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf格式的DT_RPATH段、环境变量LD_LIBRARY_PATH、/ect/ld.so.cache文件列表、/lib、/usr/bin目录找到库文件后将其载入内存中。
- 如何让系统找到动态库的解决方法:
- 拷贝自己制作的共享库到/lib或/usr/bin中(不推荐)
- 使用环境变量
- 临时设置:
- 在终端中:输入export LD_LIBRARY_PATH=动态库的路径:$LD_LIBRARY_PATH
- 在终端中:输入export LD_LIBRARY_PATH=动态库的路径:$LD_LIBRARY_PATH
- 永久设置:
- 用户级别:
- ~/.bashrc文件末尾增加:export LD_LIBRARY_PATH=动态库的路径:$LD_LIBRARY_PATH
- 配置完成:重启终端或source ~/.bashrc
- 系统级别:
- /etc/profile文件末尾增加:export LD_LIBRARY_PATH=动态库的路径
- 配置完成:source /etc/profile
- 用户级别:
- 临时设置:
- /etc/ld.so.cache文件列表
- 找到一个配置文件/etc/ld.so.conf
- 把动态库的绝对路径条件到文件中
- 执行一个命令:sudo ldconfig -v
- dlopen、dlclose、dlsym
5.静态库与动态库的工作原理与优缺点
- 静态库优缺点:
- 优点:
- 静态库被打包到应用程序中,加载速度快;
- 发布程序无需提供静态库,移植方便;
- 缺点:
- 浪费系统资源,浪费内存;
- 更新、部署、发布麻烦;
- 优点:
- 动态库(gcc test.c -L./lib -l test -o app):
- ./app
- app制作好之后,动态库没有打包到app中;
- ./app动态库不会被加载,当程序调用动态库中的函数时,动态库才会被加载;
- 程序运行前会先判断库是否存在;
- 动态链接器ld.so*需要知道动态库的路径
- 动态库优缺点:
- 优点:
- 可实现进程间的资源共享;
- 程序升级简单;
- 程序员可以控制何时加载动态库;
- 缺点:
- 加载速度比静态库满;
- 发布程序需要提供依赖的动态库;
- 优点:
- ./app