linux-dev-动态和静态库

静态库(.a)

  • 程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不在需要静态库,比较占用内存,不同程序需要加载多份
  • 程序在运行的时候可以删除

动态库(.so或.sa)

  • 程序在运行的时候才去链接共享库的代码,多个程序共享使用的代码
  • 程序在运行的时候不能被删除
  • 一个与共享库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该共享库中复制到内存中,这个过程称为动态链接
  • 共享库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间,操作系统采用虚拟内存机制允许物理内存中的一份共享库被要用到该库的所有进程共用,节省了内存和磁盘空间。

参考

  • calc.h
1
2
3
4
5
6
7
8
9
#ifndef __CALC_H__
#define __CALC_H__

extern int add(int a,int b);
extern int sub(int a,int b);
extern int mul(int a,int b);
extern int div(int a,int b);

#endif // __CALC_H__
  • calc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<calc.h>

int add(int a,int b)
{
return a+b;
}

int sub(int a,int b)
{
return a-b;
}

int mul(int a,int b)
{
return a*b;
}

int div(int a,int b)
{
return a/b;
}
  • main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>
#include<calc.h>

int main()
{
int a,b;

printf("please input a and b\n");
scanf("%d %d",&a,&b);
printf("The add:%d\n",add(a,b));
printf("The sub:%d\n",sub(a,b));
printf("The mul:%d\n",mul(a,b));
printf("The div:%d\n",div(a,b));

return 0;
}

静态库命令

1
2
3
4
5
6
7
8
9
10
11
# 生成calc库的目标文件
gcc -c calc.c -o calc.o -I.

# 生成calc库的静态文件
ar rcs -o libcalc.a calc.o

# 查看calc库包含的文件是否对
ar t libcalc.a

# 链接静态库生成可执行文件
gcc main.c -o main -I. -L. -lcalc

动态库命令

使用-l链接动态的时候可能会报错找不到库,需要执行export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH先把当前目录加到环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 生成calc库的动态库的目标文件
gcc -c calc.c -o calc.o -fPIC -I.

# 生成calc库的动态库-方法1
gcc -shared -o libcalc.so calc.o

# 生成calc库的动态库-方法2
gcc -shared -fPIC -o libcalc.so calc.c -I.

# 链接动态库生成可执行文件-方法1
gcc -o main main.c -I. ./libcalc.so

# 链接动态库生成可执行文件-方法2
gcc -o main main.c -L. -I. -lcalc

# 查看可执行文件链接了哪些动态库
ldd main