一、两种库的定义和差异
1、静态库:
静态库是以libxxx.a命名的库文件(也是一种二进制可执行的代码文件),在编译源程序的时候,如果包含了静态库,则会把整个静态库的数据都编译进程序文件。
2、动态库:
动态库是以libxxx.so命名的库文件,与静态库不同,如果源程序使用的是动态库,则不会把库的数据编译进程序,而是当程序运行到某个与动态库相关的函数时,再根据动态库留下的标记,进入动态库中寻找资源。
3、两者的区别:
由于静态库在编译程序阶段就把整个库编进去了,所以使用静态库的可执行程序会比较大。为了节省空间,如果在没有指定的情况下,linux在链接阶段通常会优先使用动态库。但是由于静态库的资源都在可执行程序的内部,所以会有更快的执行速度。这是一个时间换空间的概念,两种库的选择需要具体分析,如果库文件比较大,而且不需要很快的执行速度,尽量选择动态库。对于速度要求较高的程序,比如开机启动程序等,则更推荐使用静态库。
二、静态库的制作
1、准备好两个源码文件(即要作为静态库资源的文件)
这里以source1.c和source2.c为例:
其内容分别为两个输出字符串的函数:
#include<stdio.h>
void display1()
{
printf("this is display1!\r\n");
}
#include<stdio.h>
void display2()
{
printf("this is display2!\r\n");
}
2、将这两个源文件生成目标文件
gcc -c source1.c source2.c
3、使用ar命令制作静态库
ar -rsv libtest.a source1.o source2.o
固定格式为:ar lib(+库名称).a 依赖文件1 依赖文件2 ....
此外使用 ar -t 库名称 可以查看某个库的依赖文件
4、将静态库编译进可执行程序
gcc test1.c -o test1 -L (库文件的路径 -l(+库文件名)) //这里的库文件名是去掉lib和.a之后的
将静态库编译进可执行程序,需要在编译的时候加入 -L参数来指定库文件。
值得一提的是,如果可执行程序的源代码中如果没有对库文件内函数的声明,如下:
#include <stdio.h>
int main(void)
{
display1();
display2();
return 0;
}
在编译的时候,会报错函数未定义
test1.c: In function ‘main’:
test1.c:5:2: warning: implicit declaration of function ‘display1’ [-Wimplicit-function-declaration]
display1();
^
test1.c:6:2: warning: implicit declaration of function ‘display2’ [-Wimplicit-function-declaration]
display2();
在文件中加入对所用库函数的声明之后,成功编译和执行:
#include <stdio.h>
void display1();
void display2();
int main(void)
{
display1();
display2();
return 0;
}
三、动态库的制作
1、ldd命令的使用
使用ldd命令可以查看一个可执行程序使用了哪些.so(动态库)文件.。
2、关于配置文件
a、配置文件/etc/ld.so.conf里面存放内容为:
lzh@ubuntu16:~/study_4/static$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
在/etc/ld.so.conf.d中存放着很多的配置文件。
b、/etc/ld.so.cache文件包含了在/etc/ld.so.conf中指定的目录中查找到所有连接库。按顺序 存储。我们需要将创建的共享库加进这个文件。
c、ldconfig命令
使用ldconfig+目录名,可以将这个目录下的动态链接库被系统共享。但是这个命令是搜索/lib和/usr/lib,以及配置文件/etc/ld.so.conf里所列的目录下搜索可用的动态链接库文件的。所以我们需要将我们自己开发的库加进/lib,/usr/lib目录下,或者修改配置文件/etc/ld.so.conf ,将我们的库的路径加进去,再执行ldconfig命令,才能成功将库共享。
3、制作动态库
a、准备好源文件
source.h
1 #ifndef _SOURCE_H
2 #define _SOURCE_H
3
4 #include <stdio.h>
5 void display1();
6 void display2();
7
8 #endif
source1.c
1 #include "source.h"
2
3 void display1()
4 {
5 printf("this is display1");
6 }
source2.c
1 #include "source.h"
2
3 void display2()
4 {
5 printf("this is display2");
6 }
b、 使用gcc命令生成.so文件
gcc source1.c source2.c -fPIC -shared -o libtest.so
c、将动态库和可执行程序链接
步骤和静态库的链接一样
gcc -o test1 test1.c -L ./ -ltest
d、解决找不到.so文件的问题
①、设置环境变量
LD_LIBRARY_PATH=. 可执行文件
也可以用以下方法:
export LD_LIBRARY_PATH=.
./test1
这样在需要在同一个终端内多次执行程序时,不用输入那么长的命令。但是这样设置的环境变量也只能用于那个终端。
②、将库添加到/lib或者/usr/lib下,或者将路径添加到/etc/ld.so.conf里面
这个在前面有提到,详见三.2
以上是对静态库和动态库的浅显理解,希望以后有更多了解后能来更正和增加。
=