我们在编写代码的时候经常用到已有的接口,他们是以库的形式提供给我们使用的,而常见形式有两种,一种常以 .a 为后缀,为静态库;另一种以 .so 为后缀,为动态库。所谓的静态、动态指的是链接的过程。
程序在编译链接的时候把库的代码链接到可执行文件中,程序运行的时候将不再需要静态库。
静态库在文件中静态展开,所以有多少文件就展开多少次,非常吃内存,100M 展开 100 次,就是 10G,但是这样的好处就是静态加载的速度快。
程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
使用动态库会将动态库加载到内存,10 个文件也只需要加载一次,然后这些文件用到库的时候临时去加载,速度慢一些,但是很省内存。
静态库的名字是以 lib 开头,以 .a 结尾,例:libmylib.a
静态库生成的指令:
ar rcs libmylib.a file1.o
test.c
#include <stdio.h>
#include "sub.h"
int main(int argc, char *argv[])
{
int i = 6, j = 3;
int k;
printf("main fun! && i = %d\n", i);
k = sub_fun(i, j);
printf("k = %d\n", k);
return 0;
}
sub.c
#include <stdio.h>
int sub_fun(int a, int b)
{
printf("sub fun!\n");
return a - b;
}
sub.h
int sub_fun(int, int);
gcc -c sub.c -o sub.o
在这里插入代码片
gcc test.c libmymath.a -o test
./test
test.c 文件仅有 213 字节,而 test 文件有 16K 大小,所以静态库使用时,是直接编译到文件里面的。
动态库的名字是以 lib 开头,以 .so 结尾,例:libmylib.so
gcc -c sub.c -o sub.o -fPIC
使用 -fPIC 这个参数过后,生成的函数就和位置无关,挂上 @plt 标识,等待动态绑定
gcc -shared -o libmymath.so sub.o
gcc test.c -o test -l mymath -L ./
./test
出错原因分析:
解决办法:指定动态库路径并使其生效,然后再执行文件
通过环境变量指定动态库所在位置: export LD_LIBRARY_PATH=动态库路径
export LD_LIBRARY_PATH=./
./test
当关闭终端,再次执行 test 时,又报错。
这是因为,环境变量是进程的概念,关闭终端之后再打开,是两个进程,环境变量发生了变化。 要想永久生效,需要修改 bash 的配置文件: vi ~./bashrc
永久生效方法: