标签:cache 优缺点 添加 direct 链接库 单元 独立 后缀名 rar
函数库是现有的、可复用的代码。从本质上讲,库是一种可执行代码的二进制形式,可被操作系统载入内存执行。实际上,库就是一些头文件(.h)和库文件(.a、.so 或 .lib、.dll)的集合。Linux 将头文件和库文件分别放在 /usr/include/ 和 /usr/lib/ 目录。在某些时候程序需要的库不在这些目录下,此时需要在编译时指定所需的头文件和库文件的路径。
函数库分为静态链接库 (.a、.lib) 和动态链接库 (.so、.dll) 两种。所谓静态、动态是指链接时的状态,它们的区别在于“链接阶段”如何处理库,以链接生成可执行程序。
.a 和 .so 后缀名表示 Linux 中的静态库和动态库。
.lib 和 .dll 后缀名表示 Windows 中的静态库和动态库,
静态库的名字一般为 libxxx.a,其中 xxx 是此库的名称。
动态库的名字一般为 libxxx.so.major.minor,xxx 是该库的名称,major 是主版本号, minor 是副版本号。
gcc 在链接阶段优先使用动态链接库,只有动态链接库不存在时,才会使用静态链接库。
使用 -static 选项编译时会强制使用静态链接库。
实验文件
hello.h hello 函数的定义文件
hello.c hello 函数的实现文件
main.c 主程序
hello.h
#include <stdio.h>
void hello();
hello.c
#include "hello.h"
void hello() {
printf("hello world\n");
}
main.c
#include "hello.c"
int main(int argc, char *argv[]) {
hello();
}
静态库在链接阶段会将汇编生成的目标文件(.o 文件)与引用到的库一起链接打包生成可执行文件,这种链接方式即静态链接,此时生成的可执行程序的体积较大。由于静态库与汇编生成的目标文件一起链接成为可执行文件,因此静态库和 .o 文件相似。
实际上,静态库是一组目标文件 (.o/.obj 文件) 的集合,即多个目标文件经过打包压缩后生成的一个文件。
静态库的后缀是 .a,它的产生分为两步:
生成 hello.o 文件
$ gcc -c hello.c
生成静态库文件 libhello.a
$ ar rcs libhello.a hello.o
生成可执行程序 main
$ gcc -o main main.c -L. -lhello
静态库在链接时的路径搜索顺序:
静态库的特点:
便于移植
由于静态库在链接阶段已被加入到可执行文件中,因此程序运行时不再需要该静态库,这使得程序的移植很方便。
浪费空间和资源
所有相关的目标文件与涉及的函数都被链接到了可执行文件,因此可执行文件的体积较大。此外,若运行了很多程序,且这些程序都使用了同一个库函数,那么在内存中会大量拷贝这个库函数,这造成了内存和存储空间的浪费
动态库在编译链接阶段只将对它的引用链接到目标代码中,在程序运行时,最终的函数导入内存开始执行,函数引用被解析,此时共享库代码才被载入内存。这使得生成的可执行文件体积较小。
若不同的应用程序调用相同的共享库,那么在内存里只需维持一份该共享库的实例即可。这使得内存空间的使用大大减少。共享函数库的另一个优点是,它可以独立更新,不会影响调用它的函数。
动态库的后缀是 .so,它由 gcc 加特定参数编译产生。系统加载可执行代码时候,可自动知道其所依赖库的名字,但是并不知道库的绝对路径,此时就需要系统动态载入器 (dynamic linker/loader)。
对于 elf 格式的可执行程序,路径查找是由 ld-linux.so 来完成,它依次搜索 elf 文件的:
找到库文件后将其载入内存。
新安装的库若在 /lib 或者 /usr/lib 下,那 ld 默认能够找到。若在其他目录,则需添加到 /etc/ld.so.cache 文件:
使用 ldd 命令可以查看一个可执行程序依赖的共享库。
生成动态库文件 libhello.so
$ gcc -fPIC -c hello.c
$ gcc -shared -o libhello.so hello.o
生成可执行文件 main
$ gcc -o main main.c -L. -lhello
此时若执行 main 程序会报错
$ ./main
./main: error while loading shared libraries: libdyn.so: cannot open shared object file: No such file or directory
一种方法是将环境变量 LD_LIBRARY_PATH 设置为当前目录(程序所在的目录)。
$ export LD_LIBRARY_PATH=$(pwd)
另一种方法是将 libhello.so 文件放到 /usr/lib,目录,并使用 ldconfig 命令重建 /etc/ld.so.cache 文件(非必须)。
$ cp libhello.so /usr/lib
$ ldconfig /usr/lib
动态库和静态库的区别:
动态库的优缺点:
静态库的优缺点:
标签:cache 优缺点 添加 direct 链接库 单元 独立 后缀名 rar
原文地址:https://www.cnblogs.com/reghao/p/9418977.html