中的静态库和动态库简单介绍及生成进程示例

图片 1

在事实上的软件开辟项目中,不是每一行代码都需求大家切身写。在大家的软件出品中,有一点点代码(特别是函数卡塔尔(قطر‎的现身频率超级高,它们能够被看作公共代码来数次使用。为了制止重复劳动,大家就把那么些公共代码编写翻译为库文件,供应和需要要的次第调用。在Linux中,库分为静态库和动态库三种。

本文对静态库和动态库实行了详尽的牵线,并用实际的C代码演示了那二种库的变动进程。

图片 1

一、静态库和动态库简单介绍

鲜明,程序日常必要通过预管理、编写翻译、汇编和链接那几个步骤技术变成可实行的次序。在其实的软件开垦中,对于某些索要被广大模块一再使用的公家代码,大家就将它们编写翻译为库文件。

库是一种可进行代码的二进制格局,能够被操作系统载入内部存款和储蓄器实施。Linux援救的库分为静态库和动态库,动态库又称分享库。经常说来,Linux中的一些第一的库是贮存在lib目录下的。

静态库文件的后缀为.a,在Linux下常常命名称为libxxx.a。在链接步骤中,连接器将从静态库文件中赢得所需的代码,复制到生成的可实践文件中。因而,整个库中的全体函数都被编译进了目的代码中。

动态库文件的后缀为.so,在Linux下平常命名字为libxxx.so。相对于静态库,动态库在编写翻译的时候并不曾被编写翻译进目的代码中,而是程序实施到有关函数时才调用库中对应的函数。

能够见见,静态库的长处是编写翻译后的举行顺序无需外表的函数库帮忙,瑕疵是假使静态函数库改换了,那么你的程序必得再一次编写翻译;而动态库在四个应用程序都要动用同一函数库的时候就特别切合,但前提是前后相继的运转条件中必得提供相应的库。
无论是静态库,仍然动态库,皆以由*.o目的文件生成的。

二、静态库生成示例

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

咱俩编辑如下简单的多个程序文件:test.h、test.c和main.c,在main.c中要调用test.c中完成的函数test。
test.h文件内容:

#include <stdio.h>

void test();

test.c文件内容:

#include "test.h"

void test()
{
    printf("this is in test....../n");
}

main.c文件内容:

#include "test.h"

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 test.c
-rw------- 1 zhou dba 36 Nov  4 16:04 test.h
~/zhouzhaoxiong/zzx/mytest/a/single> gcc -c test.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 test.c
-rw------- 1 zhou dba   36 Nov  4 16:04 test.h
-rw-rw-rw- 1 zhou dba 1624 Nov  4 16:06 test.o
~/zhouzhaoxiong/zzx/mytest/a/single> ar -r libtest.a test.o
ar: creating libtest.a
~/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 libtest.a
-rw------- 1 zhou dba   80 Nov  4 16:04 test.c
-rw------- 1 zhou dba   36 Nov  4 16:04 test.h
-rw-rw-rw- 1 zhou dba 1624 Nov  4 16:06 test.o
~/zhouzhaoxiong/zzx/mytest/a/single> gcc -o test main.c libtest.a
~/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 libtest.a
-rw------- 1 zhou dba    80 Nov  4 16:04 test.c
-rw------- 1 zhou dba    36 Nov  4 16:04 test.h
-rw-rw-rw- 1 zhou dba  1624 Nov  4 16:06 test.o
~/zhouzhaoxiong/zzx/mytest/a/single> ./test
this is in test......

大家能够见到,生成库文件的指令是“ar -r libtest.a
test.o”,而将静态库文件编写翻译进代码的通令是“gcc -o test main.c
libtest.a”。

那样生成了静态库文件libtest.a之后,假设还应该有任何程序要调用test.c中落实的函数,只须要将test.h和libtest.a拷贝到对应的代码工程中,然后奉行相同“gcc
-o test main.c libtest.a”那样的吩咐就可以。

2.五个公文生成静态库示例

我们编辑如下轻易的三个程序文件:test.h、test_1.c、test_2.c、test_3.c和main.c,在main.c中要调用test_1.c、test_2.c、test_3.c中贯彻的函数test_1、test_2、test_3。

test.h文件内容:

#include <stdio.h>

void test_1();
void test_2();
void test_3();

test_1.c文本内容:

#include "test.h"

void test_1()
{
    printf("this is in test_1....../n");
}

test_2.c文本内容:

#include "test.h"

void test_2()
{
    printf("this is in test_2....../n");
}

test_3.c文书内容:

#include "test.h"

void test_3()
{
    printf("this is in test_3....../n");
}

main.c文件内容:

#include "test.h"

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 test.h
-rw------- 1 zxin10 dba 84 Nov  4 16:04 test_1.c
-rw------- 1 zxin10 dba 84 Nov  4 16:04 test_2.c
-rw------- 1 zxin10 dba 84 Nov  4 16:04 test_3.c
~/zhouzhaoxiong/zzx/mytest/a/more> gcc -c test_1.c test_2.c test_3.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 test.h
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_1.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_1.o
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_2.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_2.o
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_3.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_3.o
~/zhouzhaoxiong/zzx/mytest/a/more> ar -r libtest.a test_1.o test_2.o test_3.o
ar: creating libtest.a
~/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 libtest.a
-rw------- 1 zxin10 dba   70 Nov  4 16:04 test.h
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_1.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_1.o
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_2.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_2.o
-rw------- 1 zxin10 dba   84 Nov  4 16:04 test_3.c
-rw-rw-rw- 1 zxin10 dba 1624 Nov  4 16:15 test_3.o
~/zhouzhaoxiong/zzx/mytest/a/more> gcc -o test main.c libtest.a
~/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 libtest.a
-rw------- 1 zxin10 dba    70 Nov  4 16:04 test.h
-rw------- 1 zxin10 dba    84 Nov  4 16:04 test_1.c
-rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 test_1.o
-rw------- 1 zxin10 dba    84 Nov  4 16:04 test_2.c
-rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 test_2.o
-rw------- 1 zxin10 dba    84 Nov  4 16:04 test_3.c
-rw-rw-rw- 1 zxin10 dba  1624 Nov  4 16:15 test_3.o
~/zhouzhaoxiong/zzx/mytest/a/more> ./test
this is in test_1......
this is in test_2......
this is in test_3......

大家能够观察,生成静态库文件的下令是“ar -r libtest.a test_1.o test_2.o
test_3.o”,而将静态库文件编写翻译进代码的授命是“gcc -o test main.c
libtest.a”。

那样生成了静态库文件libtest.a之后,如若还会有其余程序要调用test_1.c、test_2.c、test_3.c中落到实处的函数,只需求将test.h和libtest.a拷贝到对应的代码工程中,然后施行相符“gcc
-o test main.c libtest.a”那样的下令就可以。

三、动态库生成示例

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

笔者们编辑如下简单的八个程序文件:so_test.h、test_a.c和test.c,在test.c中要调用test_a.c中贯彻的函数test_a。
so_test.h文件内容:

#include <stdio.h>

void test_a();

test_a.c文件内容:

#include "so_test.h"

void test_a()
{
    printf("this is in test_a.../n");
}

test.c文件内容:

#include "so_test.h"

int main()
{
    test_a();

    return 0;
}

将此多少个公文上传到Linux机器上,编写翻译生成动态库文件,之后调用库文件的成套经过如下所示:

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

在意,“./test”命令实施成功的前提是在情状变量中加多了.so文件所在的门道,这一个路子可以在“.bash_profile”文件的“LD_LIBRARY_PATH”变量的值中增加。

作者们能够寓目,生成动态库文件的命令是“gcc test_a.c -fPIC -shared -o
libtest.so”,而将动态库文件编写翻译进代码的吩咐是“gcc test.c -L. -ltest -o
test”(-L.表示近些日子路径State of Qatar。

如此那般生成了动态库文件libtest.so之后,若是还会有别的程序要调用test_a.c中贯彻的函数,只必要将so_test.h和libtest.so拷贝到对应的代码工程中,然后施行雷同“gcc
test.c -L. -ltest -o
test”那样的授命就可以(前提是libtest.so所在的路径在处境变量中设置科学卡塔尔(قطر‎。

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

咱俩编辑如下轻易的四个程序文件:so_test.h、test_a.c、test_b.c、test_c.c和test.c,在test.c中要调用test_a.c、test_b.c、test_c.c中落实的函数test_a、test_b、test_c。

so_test.h文件内容:

#include <stdio.h>

void test_a();
void test_b();
void test_c();

test_a.c文件内容:

#include "so_test.h"

void test_a()
{
    printf("this is in test_a.../n");
}

test_b.c文件内容:

#include "so_test.h"

void test_b()
{
    printf("this is in test_b.../n");
}

test_c.c文件内容:

#include "so_test.h"

void test_c()
{
    printf("this is in test_c.../n");
}

test.c文件内容:

#include "so_test.h"

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_test.h
-rw------- 1 zxin10 dba  105 Nov  4 15:25 test.c
-rw------- 1 zxin10 dba   84 Nov  4 15:25 test_a.c
-rw------- 1 zxin10 dba   84 Nov  4 15:25 test_b.c
-rw------- 1 zxin10 dba   84 Nov  4 15:25 test_c.c
~/zhouzhaoxiong/zzx/mylib/test_so> gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so
~/zhouzhaoxiong/zzx/mylib/test_so> gcc test.c -L. -ltest -o test
~/zhouzhaoxiong/zzx/mylib/test_so> ll
-rwxrwxrwx 1 zxin10 dba  8309 Nov  5 13:46 libtest.so
-rw------- 1 zxin10 dba    70 Nov  5 13:44 so_test.h
-rwxrwxrwx 1 zxin10 dba 11883 Nov  5 13:46 test
-rw------- 1 zxin10 dba   105 Nov  4 15:25 test.c
-rw------- 1 zxin10 dba    84 Nov  4 15:25 test_a.c
-rw------- 1 zxin10 dba    84 Nov  4 15:25 test_b.c
-rw------- 1 zxin10 dba    84 Nov  4 15:25 test_c.c
~/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 test_a.c test_b.c
test_c.c -fPIC -shared -o
libtest.so”,而将动态库文件编写翻译进代码的下令是“gcc test.c -L. -ltest -o
test”(-L.代表近些日子路径State of Qatar。

那样生成了动态库文件libtest.so之后,假如还应该有其它程序要调用test_a.c、test_b.c、test_c.c中贯彻的函数,只需求将so_test.h和libtest.so拷贝到相应的代码工程中,然后试行相符“gcc
test.c -L. -ltest -o
test”那样的一声令下就能够(前提是libtest.so所在的不二秘籍在情状变量中设置科学卡塔尔(قطر‎。

四、总结

至于生成静态库和动态库的授命,表达如下:

首先,在本文中,我们利用的变化静态库的通令形如“ar -r test.a
test.o”,在那之中,-r是replace的意味,表示只要当前布置的模块名早就在库中存在,则替换同名的模块。大家也得以用形如“ar
-cr test.a test.o”的命令来变化静态库,在那之中-c是create的意趣,表示生成。

第二,在本文中,大家应用的生成动态库文件的下令形如“gcc test_a.c -fPIC
-shared -o
libtest.so”,当中,fPIC表示编写翻译为地点独立的代码,shared表示生成的库为分享库。将动态库文件编写翻译进代码的命令是“gcc
test.c -L. -ltest -o
test”,-L钦命库查找的位置(注意L前边还应该有’.’卡塔尔国,表示在当前目录下搜索(假如在当前目录下的lib目录下搜寻,能够写成-L./lib卡塔尔国;-l则钦定函数库名,当中的lib和.so省略(如这里的libtest.so就简写为test卡塔尔(قطر‎。

其三,使用ldd命令能够查看叁个可执路程序信任的分享库,该命令的使用示比方下所示:

~/zhouzhaoxiong/zzx/mylib/test_so> ldd test
        linux-vdso.so.1 =>  (0x00007fff1db6e000)
        libtest.so => /home/zhou/lib/libtest.so (0x00007fdbfff21000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fdbffb95000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fdc00124000)

可以看出,可试行文件test正视于多少个分享库,当中libtest.so坐落于目前客户的lib目录下。

参考资料:

1. 
2. 
3. 

Leave a Comment.