2.静态库和动态库
一.相关概念
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库,在linux系统之下后缀名为.a
动态库(也叫共享库)( .so或.sa ):程序在运行的时候才去链接共享库的代码,多个程序共享使用库的代码。业界一般都使用动态库,因为升级方便
1、一个与共享库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
2、在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该共享库中复制到内存中,这个过程称为动态链接(dynamic linking)
3、共享库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份共享库被要用到该库的所有进程共用,节省了内存和磁盘空间。
二.静态库生成
myadd.h
extern int myadd(int a, int b);
myadd.c
int myadd(int a, int b) { return a+b; }
test.c
include <stdio.h> #include "../inc/myadd.h" int main() { int a = myadd(3,4); printf("current result is: %d\n",a); return 0; }
1. 生成.o文件
gcc -c myadd.c -o myadd.o
2. 将.o文件压成.a文件
ar rcs libmyadd.a myadd.o
3. 链接libmyadd.a这个静态库,-L代表在哪个路径之下找这个静态库,后面的.代表当前路径
gcc -L. main.c -o main.exe -lmyadd
// 若头文件与.c文件不在同一个目录,-I(大写的i)代表在哪个路径下找这个头文件,后面的../inc指的是上级目录的inc目录下
gcc -I../inc -L../ main.c -o main.exe -lmyadd
备注:
.a文件实际上是.o文件的集合,打个包而已;
ar是gnu归档工具,rcs表示(replace and create);
-lmyadd 表示要链接libmyadd.so或者libmyadd.a库文件,如果这两个库同时存在,优先链接libmyadd.so这个动态库。
三.动态库生成
1.生成动态库
-share的意思是告诉GCC编译器,把.c编译成.o然后压成.so
-fPIC是意思是生成的.so文件在链接时与位置无关,此选项必加
gcc -shared -fPIC -I./inc ./src/myadd.c -o libmyadd.so
2.链接动态库
gcc -L. main.c -o main.exe -lmyadd
PS: 若运行生成的 main.exe 出现下列错误:
error while loading shared libraries: libmyadd.so: cannot open shared object file: No such file or directory 则说明系统不知道libmyadd.so放在哪个目录下
可以cd到用户目录下,如:home/yongdaimi,执行
vim .bashrc
在.bashrc的尾部添加下列代码,指定共享库的访问路径即可。:号左边的.代表共享库可以在main.exe所在的当前目录,也可以在用户目录的lib文件夹下(home/yongdaimi/lib)
export LD_LIBRARY_PATH=.:$HOME/lib:/usr/lib:$LD_LIBRARY_PATH
备注:
1.在实际开发过程中,共享库的所在位置是很重要的,可以通过ldd main.exe查看可执行程序链接的各个共享库的位置
ldd main.exe
linux-vdso.so.1 => (0x00007fffe27fe000)
libmyadd.so => /home/yongdaimi/lib/libmyadd.so (0x00007f5d8734f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5d86f74000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5d87553000)
2.也可以通过nm 命令查看当前动态库里包含的函数列表
nm libmyadd.so
0000000000201030 B __bss_start
0000000000201030 b completed.6973
w __cxa_finalize@@GLIBC_2.2.5
0000000000000590 t deregister_tm_clones
0000000000000600 t __do_global_dtors_aux
0000000000200e08 t __do_global_dtors_aux_fini_array_entry
0000000000201028 d __dso_handle
0000000000200e18 d _DYNAMIC
0000000000201030 D _edata
0000000000201038 B _end
000000000000068c T _fini
0000000000000640 t frame_dummy
0000000000200e00 t __frame_dummy_init_array_entry
0000000000000718 r __FRAME_END__
0000000000201000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000000540 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000200e10 d __JCR_END__
0000000000200e10 d __JCR_LIST__
w _Jv_RegisterClasses
0000000000000675 T myadd
00000000000005c0 t register_tm_clones
0000000000201030 d __TMC_END__