您的位置 首页 > 娱乐休闲

Linux 中的静态库和动态库简介及生成过程示例

在实际的软件开发项目中,不是每一行代码都需要我们亲自写。在我们的软件产品中,有一些代码(尤其是函数)的出现频率很高,它们可以被当作公共代码来反复使用。为了避免重复劳动,我们就把这些公共代码编译为库文件,供需要的程序调用。在Linux中,库分为静态库和动态库两种。

本文对静态库和动态库进行了详细的介绍,并用实际的C代码演示了这两种库的生成过程。

一、静态库和动态库简介

众所周知,程序一般需要经过预处理、编译、汇编和链接这几个步骤才能变成可执行的程序。在实际的软件开发中,对于一些需要被许多模块反复使用的公共代码,我们就将它们编译为库文件。

库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。Linux支持的库分为静态库和动态库,动态库又称共享库。一般说来,Linux中的一些重要的库是存放在lib目录下的。

静态库文件的后缀为.a,在Linux下一般命名为libxxx.a。在链接步骤中,连接器将从静态库文件中取得所需的代码,复制到生成的可执行文件中。因此,整个库中的所有函数都被编译进了目标代码中。

动态库文件的后缀为.so,在Linux下一般命名为libxxx.so。相对于静态库,动态库在编译的时候并没有被编译进目标代码中,而是程序执行到相关函数时才调用库中对应的函数。

可以看到,静态库的优点是编译后的执行程序不需要外部的函数库支持,缺点是如果静态函数库改变了,那么你的程序必须重新编译;而动态库在多个应用程序都要使用同一函数库的时候就非常适合,但前提是程序的运行环境中必须提供相应的库。不管是静态库,还是动态库,都是由*.o目标文件生成的。

二、静态库生成示例

1.单个文件生成静态库示例

我们编写如下简单的三个程序文件:、和main.c,在main.c中要调用中实现的函数test。文件内容:

#include <; void test;

文件内容:

#include "" void test { printf("this is in test......\n"); }

main.c文件内容:

#include "" int main { test; return 0; }

将此三个文件上传到Linux机器上,编译生成静态库文件,之后调用库文件的整个过程如下所示:

~/zhouzhaoxiong/zzx/mytest/a/single> ll -rw------- 1 zhou dba 53 Nov  4 16:04 main.c -rw------- 1 zhou dba 80 Nov  4 16:04 -rw------- 1 zhou dba 36 Nov  4 16:04 ~/zhouzhaoxiong/zzx/mytest/a/single> gcc -c ~/zhouzhaoxiong/zzx/mytest/a/single> ll -rw------- 1 zhou dba   53 Nov  4 16:04 main.c -rw------- 1 zhou dba   80 Nov  4 16:04 -rw------- 1 zhou dba   36 Nov  4 16:04 -rw-rw-rw- 1 zhou dba 1624 Nov  4 16:06 ~/zhouzhaoxiong/zzx/mytest/a/single> ar -r lib ar: creating lib ~/zhouzhaoxiong/zzx/mytest/a/single> ll -rw------- 1 zhou dba   53 Nov  4 16:04 main.c -rw-rw-rw- 1 zhou dba 1766 Nov  4 16:06 lib -rw------- 1 zhou dba   80 Nov  4 16:04 -rw------- 1 zhou dba   36 Nov  4 16:04 -rw-rw-rw- 1 zhou dba 1624 Nov  4 16:06 ~/zhouzhaoxiong/zzx/mytest/a/single> gcc -o test main.c lib ~/zhouzhaoxiong/zzx/mytest/a/single> ll -rw------- 1 zhou dba    52 Nov  4 16:09 main.c -rwxrwxrwx 1 zhou dba 11876 Nov  4 16:09 test -rw-rw-rw- 1 zhou dba  1766 Nov  4 16:06 lib -rw------- 1 zhou dba    80 Nov  4 16:04 -rw------- 1 zhou dba    36 Nov  4 16:04 -rw-rw-rw- 1 zhou dba  1624 Nov  4 16:06 ~/zhouzhaoxiong/zzx/mytest/a/single> ./test this is in test......

我们可以看到,生成库文件的命令是“ar -r lib ”,而将静态库文件编译进代码的命令是“gcc -o test main.c lib”。

这样生成了静态库文件lib之后,如果还有其他程序要调用中实现的函数,只需要将和lib拷贝到对应的代码工程中,然后执行类似“gcc -o test main.c lib”这样的命令即可。

2.多个文件生成静态库示例

我们编写如下简单的五个程序文件:、、、和main.c,在main.c中要调用、、中实现的函数test_1、test_2、test_3。

文件内容:

#include <; void test_1; void test_2; void test_3;

文件内容:

#include "" void test_1 { printf("this is in test_1......\n"); }

文件内容:

#include "" void test_2 { printf("this is in test_2......\n"); }

文件内容:

#include "" void test_3 { printf("this is in test_3......\n"); }

main.c文件内容:

#include "" int main { test_1; test_2; test_3; return 0; }

将此五个文件上传到Linux机器上,编译生成静态库文件,之后调用库文件的整个过程如下所示:

~/zhouzhaoxiong/zzx/mytest/a/more> ll -rw------- 1 zxin10 dba 96 Nov  4 16:11 main.c -rw------- 1 zxin10 dba 70 Nov  4 16:04 -rw------- 1 zxin10 dba 84 Nov  4 16:04 -rw------- 1 zxin10 dba 84 Nov  4 16:04 -rw------- 1 zxin10 dba 84 Nov  4 16:04 ~/zhouzhaoxiong/zzx/mytest/a/more> gcc -c ~/zhouzhaoxiong/zzx/mytest/a/more> ll -rw------- 1 zxin10 dba   96 Nov  4 16:11 main.c -rw------- 1 zxin10 dba   70 Nov  4 16:04 -rw------- 1 zxin10 dba   84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 -rw------- 1 zxin10 dba   84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 -rw------- 1 zxin10 dba   84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 ~/zhouzhaoxiong/zzx/mytest/a/more> ar -r lib ar: creating lib ~/zhouzhaoxiong/zzx/mytest/a/more> ll -rw------- 1 zxin10 dba   96 Nov  4 16:11 main.c -rw-rw-rw- 1 zxin10 dba 5158 Nov  4 16:15 lib -rw------- 1 zxin10 dba   70 Nov  4 16:04 -rw------- 1 zxin10 dba   84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 -rw------- 1 zxin10 dba   84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 -rw------- 1 zxin10 dba   84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 ~/zhouzhaoxiong/zzx/mytest/a/more> gcc -o test main.c lib ~/zhouzhaoxiong/zzx/mytest/a/more> ll -rw------- 1 zxin10 dba    96 Nov  4 16:11 main.c -rwxrwxrwx 1 zxin10 dba 12008 Nov  4 16:16 test -rw-rw-rw- 1 zxin10 dba  5158 Nov  4 16:15 lib -rw------- 1 zxin10 dba    70 Nov  4 16:04 -rw------- 1 zxin10 dba    84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 -rw------- 1 zxin10 dba    84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 -rw------- 1 zxin10 dba    84 Nov  4 16:04 -rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 ~/zhouzhaoxiong/zzx/mytest/a/more> ./test this is in test_1...... this is in test_2...... this is in test_3......  

我们可以看到,生成静态库文件的命令是“ar -r lib ”,而将静态库文件编译进代码的命令是“gcc -o test main.c lib”。

这样生成了静态库文件lib之后,如果还有其他程序要调用、、中实现的函数,只需要将和lib拷贝到对应的代码工程中,然后执行类似“gcc -o test main.c lib”这样的命令即可。

三、动态库生成示例

1.单个文件生成动态库示例

我们编写如下简单的三个程序文件:so_、和,在中要调用中实现的函数test_a。so_文件内容:

#include <; void test_a;

文件内容:

#include "so_" void test_a { printf("this is in test_a...\n"); }

文件内容:

#include "so_" int main { test_a; return 0; }

将此三个文件上传到Linux机器上,编译生成动态库文件,之后调用库文件的整个过程如下所示:

~/zhouzhaoxiong/zzx/mylib/so> ll -rw------- 1 zxin10 dba  95 Nov  4 17:37 so_ -rw------- 1 zxin10 dba 109 Nov  4 17:37 -rw------- 1 zxin10 dba  84 Nov  4 10:57 ~/zhouzhaoxiong/zzx/mylib/so> gcc -fPIC -shared -o lib ~/zhouzhaoxiong/zzx/mylib/so> ll -rwxrwxrwx 1 zxin10 dba 8181 Nov  4 17:43 lib -rw------- 1 zxin10 dba   95 Nov  4 17:37 so_ -rw------- 1 zxin10 dba  109 Nov  4 17:37 -rw------- 1 zxin10 dba   84 Nov  4 10:57 ~/zhouzhaoxiong/zzx/mylib/so> gcc -L. -ltest -o test ~/zhouzhaoxiong/zzx/mylib/so> ll -rwxrwxrwx 1 zxin10 dba  8181 Nov  4 17:43 lib -rw------- 1 zxin10 dba    95 Nov  4 17:37 so_ -rwxrwxrwx 1 zxin10 dba 11805 Nov  4 17:44 test -rw------- 1 zxin10 dba   109 Nov  4 17:37 -rw------- 1 zxin10 dba    84 Nov  4 10:57 ~/zhouzhaoxiong/zzx/mylib/so> ./test this is in test_a...

注意,“./test”命令执行成功的前提是在环境变量中添加了.so文件所在的路径,这个路径可以在“.bash_profile”文件的“LD_LIBRARY_PATH”变量的值中添加。

我们可以看到,生成动态库文件的命令是“gcc -fPIC -shared -o lib”,而将动态库文件编译进代码的命令是“gcc -L. -ltest -o test”(-L.表示当前路径)。

这样生成了动态库文件lib之后,如果还有其他程序要调用中实现的函数,只需要将so_和lib拷贝到对应的代码工程中,然后执行类似“gcc -L. -ltest -o test”这样的命令即可(前提是lib所在的路径在环境变量中设置正确)。

2.多个文件生成动态库示例

我们编写如下简单的五个程序文件:so_、、、和,在中要调用、、中实现的函数test_a、test_b、test_c。

so_文件内容:

#include <; void test_a; void test_b; void test_c;

文件内容:

#include "so_" void test_b { printf("this is in test_b...\n"); }

文件内容:

#include "so_" void test_c { printf("this is in test_c...\n"); }

文件内容:

#include "so_" int main { test_a; test_b; test_c; return 0; }

将此五个文件上传到Linux机器上,编译生成动态库文件,之后调用库文件的整个过程如下所示:

~/zhouzhaoxiong/zzx/mylib/test_so> ll -rwxrwxrwx 1 zxin10 dba 8309 Nov  5 09:12 libtest -rw------- 1 zxin10 dba   70 Nov  5 13:44 so_ -rw------- 1 zxin10 dba  105 Nov  4 15:25 -rw------- 1 zxin10 dba   84 Nov  4 15:25 -rw------- 1 zxin10 dba   84 Nov  4 15:25 -rw------- 1 zxin10 dba   84 Nov  4 15:25 ~/zhouzhaoxiong/zzx/mylib/test_so> gcc -fPIC -shared -o lib ~/zhouzhaoxiong/zzx/mylib/test_so> gcc -L. -ltest -o test ~/zhouzhaoxiong/zzx/mylib/test_so> ll -rwxrwxrwx 1 zxin10 dba  8309 Nov  5 13:46 lib -rw------- 1 zxin10 dba    70 Nov  5 13:44 so_ -rwxrwxrwx 1 zxin10 dba 11883 Nov  5 13:46 test -rw------- 1 zxin10 dba   105 Nov  4 15:25 -rw------- 1 zxin10 dba    84 Nov  4 15:25 -rw------- 1 zxin10 dba    84 Nov  4 15:25 -rw------- 1 zxin10 dba    84 Nov  4 15:25 ~/zhouzhaoxiong/zzx/mylib/test_so> ./test this is in test_a... this is in test_b... this is in test_c...

注意,“./test”命令执行成功的前提仍然是在环境变量中添加了.so文件所在的路径,这个路径可以在“.bash_profile”文件的“LD_LIBRARY_PATH”变量的值中添加。

我们可以看到,多个文件生成动态库文件的命令是“gcc -fPIC -shared -o lib”,而将动态库文件编译进代码的命令是“gcc -L. -ltest -o test”(-L.表示当前路径)。

这样生成了动态库文件lib之后,如果还有其他程序要调用、、中实现的函数,只需要将so_和lib拷贝到对应的代码工程中,然后执行类似“gcc -L. -ltest -o test”这样的命令即可(前提是lib所在的路径在环境变量中设置正确)。

四、总结

有关生成静态库和动态库的命令,说明如下:

第一,在本文中,我们使用的生成静态库的命令形如“ar -r ”,其中,-r是replace的意思,表示如果当前插入的模块名已经在库中存在,则替换同名的模块。我们也可以用形如“ar -cr ”的命令来生成静态库,其中-c是create的意思,表示生成。

第二,在本文中,我们使用的生成动态库文件的命令形如“gcc -fPIC -shared -o lib”,其中,fPIC表示编译为位置独立的代码,shared表示生成的库为共享库。将动态库文件编译进代码的命令是“gcc -L. -ltest -o test”,-L指定库查找的位置(注意L后面还有'.'),表示在当前目录下查找(如果在当前目录下的lib目录下查找,可以写成-L./lib);-l则指定函数库名,其中的lib和.so省略(如这里的lib就简写为test)。

第三,使用ldd命令可以查看一个可执行程序依赖的共享库,该命令的使用示例如下所示:

~/zhouzhaoxiong/zzx/mylib/test_so> ldd test         linux-vd =>  (0x00007fff1db6e000)         lib => /home/zhou/lib/lib (0x00007fdbfff21000)         libc. => /lib64/libc. (0x00007fdbffb95000)         /lib64 (0x00007fdc00124000)

可以看到,可执行文件test依赖于四个共享库,其中lib位于当前用户的lib目录下。

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“如何调用静态库,如何调用静态库里面的函数,如何调用静态库文件,静态库调用静态库”边界阅读