静态库与动态库
库是写好的、现有的、成熟的、可以复用的代码。现实中很多程序都要依赖很多基础的底层库文件,不可能所有的代码都从零开始,因此库的存在意义非同寻常。
库有两种,分别为静态库和动态库。在类unix环境下,静态库一般以==.a结尾,动态库一般以.so==结尾。而在windows环境下静态库以.lib结尾,动态库以.dll结尾。
静态库的特点:
1.静态库是在链接阶段被打包到可执行程序中,并且作为可执行程序的一部分
2.程序在运行时,与静态库再无瓜葛,移植方便 #静态库被连接后生成可执行程序,这时将静态库删掉,程序也能运行
3.浪费空间,每一个进程中都有一个静态库的副本。
4.对程序的更新,部署、发布不友好。 #一旦更行,则需要重新链接
动态库的特点:
1.在链接阶段并不会被打包到可执行程序中,而在程序运行的时候才加载
2.动态库可以在进程间共享(又称共享库)
3.对程序的更行、部署、发布友好(只需更新动态库就好了)
4.程序在运行时,依赖动态库,不方便移植
根据下篇代码生成库文件:
#ifndef __WD_ALGS_H
#define __WD_ALGS_H
int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int div(int a, int b);
#endif
// add.c
#include "algs.h"
int add(int a, int b) {
return a + b;
}
// sub.c
#include "algs.h"
int sub(int a, int b) {
return a - b;
}
// mul.c
#include "algs.h"
int mul(int a, int b) {
return a * b;
}
// div.c
#include "algs.h"
int div(int a, int b) {
return a / b;
}
//main.c
#include <stdio.h>
#include "algs.h"
int main(void) {
printf("add(7, 3)=%d\n", add(7,3));
printf("sub(7, 3)=%d\n", sub(7,3));
printf("mul(7, 3)=%d\n", mul(7,3));
printf("div(7, 3)=%d\n", div(7,3));
return 0;
}
生成静态库:
#1.生成目标文件
$ gcc -c add.c
$ gcc -c sub.c
$ gcc -c sub.c
$ gcc -c sub.c
#2.将目标文件打包成静态库
$ ar crsv libalgs.a add.o sub.o mul.o div.o #静态库一般以.a结尾,库的名字为algs
#3.将静态库移动到/usr/lib目录下
$ mv libalgs.a /usr/lib
#4.编译源文件并将静态库链接到程序
$ gcc main.c -o main -lalgs # -l是链接命令,后面跟库文件的名称
$ ./main
#删除掉链接库,程序还是能够运行:因为在链接阶段程序就被打包到可执行程序了,并且作为可执行程序的一部分,所以这时删掉静态库,不会影响程序的执行
生成动态库
#1.生成目标文件需要加上 -fpic选项
gcc -c add.c -fpic
gcc -c sub.c -fpic
gcc -c mul.c -fpic
gcc -c div.c -fpic
#2.将目标文件打包成动态库
gcc -shared add.o sub.o mul.o div.o -o libalgs.so #动态库以.so结尾
#3.将动态库移动到usr/lib目录下
$ mv libalgs.so /usr/lib
#4.将动态库链接到程序
gcc main.c -o main -lags # -o指定可执行程序的名称
./main #执行程序
#执行结果:
##########################
add(7, 3)=10
sub(7, 3)=4
mul(7, 3)=21
div(7, 3)=2
##########################
使用动态库,更行是非常容易的,我们只需更新动态库即可,不需要重新生成可执行程序。并且一般不会删除旧的动态库,只是修改符号链接的指向就行
我们可以对add.c, sub.c,mul.c,div.c做如下修改== printf(“modify.\n”)==
#ifndef __WD_ALGS_H
#define __WD_ALGS_H
int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int div(int a, int b);
#endif
// add.c
#include "algs.h"
int add(int a, int b) {
printf("modify.\n");
return a + b;
}
// sub.c
#include "algs.h"
int sub(int a, int b) {
printf("modify.\n");
return a - b;
}
// mul.c
#include "algs.h"
int mul(int a, int b) {
printf("modify.\n");
return a * b;
}
// div.c
#include "algs.h"
int div(int a, int b) {
printf("modify.\n");
return a / b;
}
//main.c
#include <stdio.h>
#include "algs.h"
int main(void) {
printf("add(7, 3)=%d\n", add(7,3));
printf("sub(7, 3)=%d\n", sub(7,3));
printf("mul(7, 3)=%d\n", mul(7,3));
printf("div(7, 3)=%d\n", div(7,3));
return 0;
}
#1.生成目标文件需要加上 -fpic选项
gcc -c add.c -fpic
gcc -c sub.c -fpic
gcc -c mul.c -fpic
gcc -c div.c -fpic
#2.将目标文件打包成动态库
gcc -shared add.o sub.o mul.o div.o -o libalgs.so.0.1 #动态库以.so结尾
#3.将动态库移动到usr/lib目录下
$ mv libalgs.so.0.1 /usr/lib
#4. cd到/usr/lib目录下
$ cd /usr/lib
#5.创建符号链接,将其指向新的动态库
$ ln -s libalgs.so.0.1 libalgs.so #这样就不会覆盖旧的动态库
#cd回去
$ cd -
#7. 执行程序
./main
=========================执行结果=============================
I love xixi
add(7, 3)=10
I love xixi
sub(7, 3)=4
I love xixi
mul(7, 3)=21
I love xixi
div(7, 3)=2
由于动态库对于更新、发布非常友好,故现代的大多数程序都是动态库!