静态链接库与动态链接库
所谓“程序库”,简单说,就是包含了数据和执行码的文件。其不能单独执行,可以作为其它执行程序的一部分来完成某些功能。
库的存在可以使得程序模块化,可以实现代码重用,并且可以对外保密库中内容。
程序库可分静态库(static library)和共享库(shared library)。
静态库制作和使用
静态库可以认为是一些目标代码的集合,是在可执行程序运行前就已经加入到执行码中,成为执行程序的一部分。
按照习惯,一般以“.a
”做为文件后缀名。静态库的命名一般分为三个部分:
- 前缀:
lib
- 库名称:自己定义即可
- 后缀:
.a
所以最终的静态库的名字应该为:libxxx.a
1) 静态库制作
在使用ar
工具是时候需要添加参数:rcs
r
更新c
创建s
建立索引
ar -rcs libtest.a add.o sub.o
2)静态库使用
静态库制作完成之后,需要将.a文件和头文件一起发布给用户。
假设测试文件为test.c
,静态库文件为libtest.a
,头文件在当前目录
编译命令:
gcc test.c -I. -L. -ltest -o test.out
参数说明:
-
-I .
: 表示指定头文件的目录为当前目录 -
-L .
:表示要连接的库所在目录 -
-l
(小写L):指定链接时需要的库,去掉前缀和后缀
动态库制作和使用
共享库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。
动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。
按照习惯,一般以“.so
”做为文件后缀名。共享库的命名一般分为三个部分:
- 前缀:
lib
- 库名称:自己定义即可
- 后缀:
.so
所以最终的动态库的名字应该为:libxxx.so
1)动态库制作
步骤一: 生成目标文件,此时要加gcc
编译选项:-fPIC(fpic)
参数:-fPIC
创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。
gcc -fpic -c add.c
gcc -fpic -c sub.c
生成.o
文件
步骤二: 生成共享库,此时要加链接器选项: -shared
(指定生成动态链接库)
gcc -shared add.o sub.o -o libtest.so
2)动态库测试
gcc test.c -I. -L. -ltest -o test.out
引用动态库编译成可执行文件(跟静态库方式一样)。然后运行:./a.out
,发现竟然报错了!!!
3)如何让系统找到动态库
五种方法:
-
拷贝自己制作的共享库到
/lib
或者/usr/lib
(不能是/lib64目录)sudo cp libtest.so /lib
-
使用符号链接, 但是一定要使用绝对路径
sudo ln -s `pwd`/libtest.so /lib/libtest.so
-
临时设置
LD_LIBRARY_PATH
:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`
-
永久设置,把
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径
,设置到~/.bashrc
文件中vim ~/.bashrc # 添加 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd` source ./bashrc
-
将其添加到
/etc/ld.so.conf
文件中 (GNU系统下)sudo vim /etc/ld.so.conf # 添加 库所在目录 sudo ldconfig -v
注意:LD_LIBRARY_PATH
是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径(/lib 或 /usr/lib
)之外的其他路径。可以LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH.(newdirs是新的路径串)
追加一个路径,前提是LD_LIBRARY_PATH
这个环境变量必须存在,如果不存在要用export
设置为新的环境变量(export
也可以追加)