静态库与动态库
静态库与动态库都是二进制文件
静态库
静态库的名字一般以lib前缀开头,以.a结尾 ,例如c静态库为 libc.a
静态库(.a):程序在编译链接的时候将库的代码链接到可执行文件中。程序运行的时候就不需要静态库了。(程序将需要的代码拷贝一份到可执行文件中,此后再运行时就不需要静态库了)
生成静态库:
先生成二进制的.o 文件
[wens@localhost 10_19]$ ls
add.c add.h Makefile sub.c sub.h main.c
//创建文件,并写makefile
1 #include <stdio.h>
2
3 int add(int a,int b)
4 {
5
6 return a+b;
7 }
1 #include <stdio.h>
E> 2 #include ”sub.h“
E> 3 #include ”add.h“
4 int main()
5 {
6 int a=1;
7 int b=2;
E> 8 printf("%d\n",add(a,b));
E> 9 printf("%d\n",sub(b,a));
10 return 0;
11 }
//makefile
libmymath.a:add.o sub.o
2 ar -rc libmymath.a add.o sub.o
3 // ar是gun的归档工具 rc 表示 (replace和create)
4 add.o: add.c
5 gcc -c add.c -o add.o
6 sub.o: sub.c
7 gcc -c sub.c -o sub.o
8 .PHONY:clean
9 clean:
10 rm -f *.o libmymath.a
生成静态库
[wens@localhost 10_19]$ make
gcc -c add.c -o add.o
gcc -c sub.c -o sub.o
ar -rc libmymath.a add.o sub.o
查看静态库的目录列表
[wens@localhost 10_19]$ ar -tv libmymath.a
rw-rw-r-- 1000/1000 1240 Oct 19 03:25 2018 add.o
rw-rw-r-- 1000/1000 1240 Oct 19 03:25 2018 sub.o
//t:列出静态库中的文件
//v:verbose 列出详细内容
链接静态库
gcc main.c -L. -lmymath
[wens@localhost 10_19]$ ls
add.c add.h add.o a.out libmymath.a main.c Makefile sub.c sub.h sub.o
[wens@localhost 10_19]$ ./a.out
3
1
//-L 指定库的路径
//-l 指定库的名字(去掉前缀lib 和后缀 .a)
目标文件生成后,删去静态库后,程序仍能运行
wens@localhost 10_19]$ make clean
rm -f *.o libmymath.a
[wens@localhost 10_19]$ ./a.out
3
1
[wens@localhost 10_19]$
当库较多时,头文件较多时,比较杂乱,我们将 生成的静态库打包 把头文件放在一起 在把库文件放在一起
[wens@localhost 10_19]$ mkdir mylib include lib
[wens@localhost 10_19]$ ls
add.c add.h a.out include lib main.c Makefile mylib sub.c sub.h
[wens@localhost 10_19]$ mv add.h sub.h include
wens@localhost 10_19]$ mv libmymath.a lib
[wens@localhost 10_19]$ mv include lib mylib
[wens@localhost 10_19]$ gcc main.c -I./mylib/include -L./mylib/lib -lmymath
[wens@localhost 10_19]$ ls
add.c add.o a.out libmymath.a main.c Makefile mylib sub.c sub.o
[wens@localhost 10_19]$ ./a.out
3
1
[wens@localhost 10_19]$
- -I 指定头文件的路径
- -L 指定静态库的路径
库的搜索路径
- -L指定的路径
- 系统默认路径 /usr/lib
- 由环境变量指定 (LIBARAY_PATH)
动态库
动态库(.so):程序运行才去链接动态库的代码,多个程序共享使用库的代码。
(动态库的内容存放在磁盘中,需要链接时即将所需动态库的内容加载到物理内存中,再映射到虚拟地址空间中堆区和栈区中间的共享区)
按需加载:
一个动态库链接的可执行文件仅仅包含他用到的函数入口地址的一个表而不是外部函数所在目标文件的整个机器码
动态链接:
在可执行文件运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接
动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。
因为虚拟内存机制使得,物理内存中的一份动态库可以被多个使用该哭的进程共享,节省内存和磁盘空间。
生成动态库
采用之前写好的文件
写makefile
1 libmymath.so:add.c sub.c
2 gcc -fPIC -c add.c sub.c //产生位置无关码
3 gcc -shared -o libmymath.so *.o //表示生成共享库格式
4
5 add.o:add.c
6 gcc -c add.c -o add.o
7 sub.o:sub.c
8 gcc -c sub.c -o sub.o
9 .PHONY:clean
10 clean:
11 rm -f libmymath.so *.o
生成动态库
[wens@localhost lib2]$ make
gcc -fPIC -c add.c sub.c
gcc -shared -o libmymath.so *.o
[wens@localhost lib2]$ ls
add.c add.o libmymath.so makefile sub.c sub.o
使用动态库
[wens@localhost lib2]$ gcc main.c -I. -L. -lmymath
[wens@localhost lib2]$ ls
add.c add.h add.o a.out libmymath.so main.c makefile sub.c sub.h sub.o
[wens@localhost lib2]$ ./a.out
3
1
-I 头文件路径
-L 库路径
-l 库名 (去掉前缀和后缀)
删除后程序不可再执行
[wens@localhost lib2]$ gcc main.c -I. -L. -lmymath
[wens@localhost lib2]$ ./a.out
3
1
[wens@localhost lib2]$ make clean
rm -f libmymath.so *.o
[wens@localhost lib2]$ gcc main.c -I. -L. -lmymath
/usr/bin/ld: cannot find -lmymath
collect2: error: ld returned 1 exit status
[wens@localhost lib2]$
查看动态库的依赖关系
[wens@localhost lib2]$ ldd a.out
linux-vdso.so.1 => (0x00007ffea83f5000)
libmymath.so => not found //生成时未设置路经,所以未找到
libc.so.6 => /lib64/libc.so.6 (0x00007ff4479cb000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff447d98000)
设置环境变量
[wens@localhost lib2]$ gcc main.c -I. -L. -lmymath
[wens@localhost lib2]$ ldd a.out
linux-vdso.so.1 => (0x00007ffc66305000)
libmymath.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007f395f343000)
/lib64/ld-linux-x86-64.so.2 (0x00007f395f710000)
[wens@localhost lib2]$ echo $LD_LIBRARY_PATH
./lib2/
[wens@localhost lib2]$ export LD_LIBRARY_PATH=./
[wens@localhost lib2]$ echo $LD_LIBRARY_PATH
./
[wens@localhost lib2]$ ldd a.out
linux-vdso.so.1 => (0x00007ffff136d000)
libmymath.so => ./libmymath.so (0x00007ff35ee3a000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff35ea6d000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff35f03c000)
静态库与动态库的区别:
静态库 | 动态库 |
---|---|
以.a 结尾 | 以.so 结尾 |
链接一次 | 每次都要链接 |
可删 | 不可删 |
链接时拷贝 | 不拷贝 |