概念介绍
linux 下静态库以 .a 为后缀,动态库以 .so 为后缀。静态库、动态库的区别在于链接阶段(链接成可执行程序)如何处理库。链接方式有两种:静态链接方式、动态链接方式。
静态库
在程序编译时会被连接到目标代码中,生成可执行 bin 文件后,不再需要该静态库了。
静态库总结:
- 编译时完成链接,运行不再需要,方便移植
- 不方便新版本发布,换库需对整个程序重新编译
- 多个可执行程序共用一个静态库时,每个程序对应的 bin 都存在一份对它的拷贝,浪费空间
动态库
在程序执行时才进行链接,所以即使生成 bin 文件后,也需要动态库才能运行。
动态库总结:
- 运行时链接,可实现进程间的资源共享,所以动态库也称共享库
- 方便版本迭代,只需将生成的新版动态库重新发给用户
- 可以在程序中显示链接,需要才链接
案例
在 lib_practice
目录下有下面三个源文件,如何让 main
函数能够通过编译并执行呢?也就是说如何在 main
中使用 hello
方法。
hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char* msg);
#endif
hello.c
#include <stdio.h>
void hello(const char* msg) {
printf("hello %s! \n", msg);
}
main.c
#include "hello.h"
int main() {
hello("everyone");
return 0;
}
有三个方法:
- 使用
gcc -c
,将main.c
,hello.c
分别编译成目标文件,main.o
,hello.o
,再使用gcc -o
将这两个.o
文件合成一个可执行文件 - 使用
gcc -c
将hello.c
编译成目标文件hello.o
,再使用ar
工具将hello.o
打包成静态库文件,生成 bin 文件时指定需要链接的静态库 - 使用
gcc -shared -fPCI -o
生成动态库,gcc
链接动态库,将动态库放到 linux 默认搜索路径下
方法一
root@Tomorrow:~/CodeSpace/primer/lib_pratice# gcc -c main.c hello.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
hello.c hello.h hello.o main.c main.o
root@Tomorrow:~/CodeSpace/primer/lib_pratice# gcc -o say_hello main.o hello.o
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
hello.c hello.h hello.o main.c main.o say_hello
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ./say_hello
hello everyone!
方法二
root@Tomorrow:~/CodeSpace/primer/lib_pratice# gcc -c hello.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
hello.c hello.h hello.o main.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ar crv libhello.a hello.o
a - hello.o
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
hello.c hello.h hello.o libhello.a main.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# gcc -o say_hello main.c -L/root/CodeSpace/primer/lib_pratice -lhello
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
hello.c hello.h hello.o libhello.a main.c say_hello
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ./say_hello
hello everyone!
删除静态库,看看 bin 文件是否仍然可执行:
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
hello.c hello.h hello.o libhello.a main.c say_hello
root@Tomorrow:~/CodeSpace/primer/lib_pratice# rm libhello.a
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ./say_hello
hello everyone!
ok,测试通过。
方法三
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
hello.c hello.h main.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# gcc -shared -fPIC -o libhello.so hello.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
hello.c hello.h libhello.so main.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# gcc main.c -L. -lhello
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ls
a.out hello.c hello.h libhello.so main.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ./a.out
./a.out: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
执行发现找不到动态库,这是因为 libhello.so 不在 linux 的默认寻找路径下,需要将它移入 /lib 或 /usr/lib 目录才行:
root@Tomorrow:~/CodeSpace/primer/lib_pratice# mv libhello.so /usr/lib
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ll
total 36
drwxr-xr-x 2 root root 4096 5月 21 22:28 ./
drwxr-xr-x 3 root root 4096 5月 21 10:56 ../
-rwxr-xr-x 1 root root 15944 5月 21 22:20 a.out*
-rw-r--r-- 1 root root 81 5月 21 10:59 hello.c
-rw-r--r-- 1 root root 70 5月 21 10:57 hello.h
-rw-r--r-- 1 root root 66 5月 21 11:00 main.c
root@Tomorrow:~/CodeSpace/primer/lib_pratice# ./a.out
hello everyone!
转载请注明:XAMPP中文组官网 » Linux 下库的介绍与链接