Linux下的动态库与静态库

2019-09-25

关键字:生成库、静态库引用、动态库引用


在 C 开发中,“库”是一个经常听到的名词。

所谓的库其实就是一个二进制文件。这个二进制文件的内容是可被其它C程序调用执行的函数。换句话说,库就是一组C代码的打包形式而已,打包是指将源代码以库的形式编译而生成的文件。

不过即使它只是源代码的打包,它也仍然是有系统专有性的,即不同系统下编译出来的库并不能互相兼容使用。

C库可分为动态库静态库两种。引用了外部库的应用程序在编译时会在”链接期“处理库与程序源码之间的关系。

1、静态库

静态库顾名思义,它并不是“动态共享”的,每一个程序引用到一个静态库,就会在编译时将该静态库一起编译进去,即将静态库直接打包进引用它的程序中。

静态库文件的后缀是 .a,即常说的 A 文件。

静态库具有以下几个特点:

1、库中直接包含源码,在程序编译时直接将库中的源码打包到可执行文件中;

2、程序在运行时无需加载库文件,因而速度更快;

3、引用静态库的程序需要占用更多的磁盘空间;

4、静态库升级后需要重新编译所有引用了它的程序;

创建静态库:

1、设计库原型;

2、实现库的代码;

3、编译库源码生成 O 文件: gcc -c xxx.c -Wall;

4、通过 ar 命令将 O 文件生成静态库文件: ar crs libxxx.a xxx.o;

5、可以通过 nm 命令查看静态库信息: nm libxxx.a

Linux 中的静态库的名称是有规则的,必须以 lib 开头、以 .a 作为后缀。

调用静态库:

1、在需要引用到静态库中函数的源码里声明该函数的原型,通常静态库文件会提供一个头文件专门给外部程序调用使用;

2、直接在需要的地方调用静态库中的函数;

3、编译:gcc -o xxx2 xxx2.c -L. -lxxx;

-L 是设定库的查找路径。gcc 在编译时默认只会去 /lib, /usr/lib 等官方库目录下查找,但我们编译生成的静态库不一定放在那些目录中,所以要明确告诉编译器应该去哪里查找。后面的小圆点就表示在当前目录下查找库。

-lxxx 就是指明要链接的库的名称了。这里要注意,-l 后面接的是库的名称而不是库文件的名称,简单理解成是去掉库文件名称前面的 lib 前缀以及 .a 后缀后和字符串就行了。

也可以使用另一种编译选项: gcc -o xxx2 xxx2.c -L. -static -lxxx

4、编译完成,直接运行程序即可。

2、动态库

动态库与静态库相反,它是具有”全局共享性“的。一个程序在引用了共享库后,编译时仅会记录用到哪个共享库中的哪一个符号,并不会像静态库那样将库中代码一并打包到本应用程序中。

因此,动态库的特点基本上与静态库的相反:

1、编译结果更小;

2、多个程序可共享同一个库;

3、程序运行时需要先加载共享库;

4、动态库的升级直接替换库文件即可,一般不需要重新编译引用了库的程序。

创建动态库:

1、设计库原型并实现代码;

2、编译共享库源码生成 O 文件:gcc -c fPIC xxx.c -Wall;

3、将 O 文件生成为共享库文件: gcc -shared -o libxxx.so.1 xxx.o;

共享库文件的命名规则与静态库类似,都有固定的前缀后缀。中间的 xxx 即为库名称。.so 表示这个文件是一个动态库文件。.1 通常表示库的版本号,这样可以实现多个库版本共存的需求。

4、为共享库文件创建符号链接:ln -s libxxx.so.1 libxxx.so;

引用动态库:

1、声明库中函数接口,与上面静态库中的引用方法一致;

2、编译: gcc -o xxx2 xxx2.c -L. -lxxx;

gcc 在引用库时,首先会去查找动态库,当找不到动态库时才去查找静态库,静态库也找不到则会报错。

3、执行程序;

Linux 在运行时默认只会去缺省的几个目录下查找动态库并加载,若我们编译出来的动态库没有放在缺省库目录下,则会报找不到动态库的错误。解决的办法有:

1、扩展库加载路径: export LD_LIBRARY_PATH=xxx:$LD_LIBRARY_PATH; xxx 就是有这个动态库文件的路径。

2、将这个动态库放到缺省库目录下: /lib, /usr/lib;

3、新建 /etc/ld.so.conf.d/xxx.conf 文件,在这个文件中填写我们的动态库的路径,保存以后再执行 ldconfig 命令刷新系统变量;


猜你喜欢

转载自www.cnblogs.com/chorm590/p/11588029.html