1、动态库静态库的概念
动态库和静态库是在软件开发中常见的库文件类型,用于存储可重用的代码和资源,以便在程序中进行调用。
静态库(Static Library): 静态库是一组预编译的目标文件(通常是 .lib 文件),其中包含了一组函数和数据,可以被链接到程序中。静态库在编译时将库中的代码复制到最终可执行文件中,因此可执行文件比较大。每次程序被编译时,静态库都会被复制到最终的可执行文件中,因此可以在不同的环境中运行。
动态库(Dynamic Library): 动态库是一组已被编译成共享对象文件(通常是 .dll 文件,在 Windows 系统中)的代码和资源,可以在运行时被程序动态加载和链接,也就是说,动态库的代码在程序运行时才被载入内存,不会在编译时被复制到可执行文件中。这使得可执行文件较小,但在程序运行时需要确保系统能够找到动态库。
区别:
- 静态库在编译时被链接到可执行文件中,程序运行时不再需要库文件,但会使得可执行文件变大。
- 动态库在程序运行时才被加载,可以被多个程序共享使用,节省内存空间,但需要确保系统能找到对应的库文件。
在选择使用动态库还是静态库时,需要考虑项目的需求、平台的支持、便捷性等因素。
2、程序的编译过程
- 程序在编译时分为多个阶段:
- 预处理
- 处理所有预处理命名,包括宏定义、条件编译指令、文件包含指令
- 编译
- 进行词法分析、语法分析、语义分析后,将代码翻译成汇编指令
- 汇编
- 将汇编指令翻译成机器指令,也就是二进制,形成目标文件
- 链接
- 将多个目标文件进行链接,得到一个程序最后的执行文件
- 预处理
编译过程演示
预处理:
gcc -E main.c -o main.i
编译:
gcc -S main.i -o main.s
汇编:
gcc -c main.s -o main.o
链接:
gcc main.o -o main
3、静态库
静态库的文件格式
- 静态库是函数库二进制文件的一种形式,在 windows 与 Linux 下对应的文件类型
- Windows :name.lib
- Linux: libname.a
静态库的特点
- 静态库的特点:
- 当编译器链接静态库的时候,如果在可执行文件中有调用静态库的函数接口,则会将静态拷贝到可执行文件中
- 由于可执行文件中有静态库中函数接口的实现代码,运行的时候不需要静态库
- 由于链接的时候,需要将库函数接口实现代码拷贝到可执行文件中,所以生成
静态库的制作
- 静态库的制作:
- 将 file.c 编译成 file.o
gcc -c main.c -o main.o
- 将 file.o 生成静态库
ar -rs main.a main.o
生成静态库main.a
-
ar 命令用于制作静态库的命令,可以使用一些常用的选项
- -s:将目标文件的索引符号添加到库中
- -r : 在库中更新文件或者添加新的文件
-
静态库在链接使用时需要指定头文件的位置与静态库的位置
- -I : 指定头文件
- -L: 指定库的位置
- -l : 指定链接的库的名字
gcc -I<头文件路径> -L<库的路径> -l<静态库的名字> -o <可执行文件名>
- gcc 编译器默认搜索头文件与库文件的路径
- /usr/include 为头文件默认路径
- /usr/lib 与 /lib 为库的默认路径
静态库的优点与缺点
-
优点
- 可执行程序在执行的时候,不需要加载动态库,可以直接运行
-
缺点
- 多个程序链接静态库的时候,需要拷贝多份静态库的代码,占用的内存较多
4、动态库
动态库的文件格式
- 动态库的文件格式如下:
- Windows : name.dll
- Linux : libname.so
动态库的特点
- 当编译器链接动态库的时候,会在可执行文件的头信息中记录库的名字,便于在操作系统执行这个可执,让操作系统去加载对应的动态库。
- 当操作系统执行可执行文件时候,会先读取可执行文件的头信息,然后加载头信息中记录的动态库到内存中运行
- 当可执行文件调用动态库中的函数时,则需要加载动态库到内存中
动态库的制作
- 动态库的制作过程如下:
- 将 file.c 编译成 file.o
gcc -c file.c -o file.o
- 将 file.o 生成动态库
gcc -shared file.o -o libfile.so
动态库的链接
- 动态库库在链接使用时需要指定头文件的位置与动态库库的位置
- -I : 指定头文件
- -L: 指定库的位置
- -l : 指定链接的库的名字
gcc -I<头文件路径> -L<库的路径> -l<动态库的名字> <源文件>-o <可执行文件名>
-
gcc 编译器默认搜索头文件与库文件的路径
- /usr/include 为头文件默认路径
- /usr/lib 与 /lib 为库的默认路径
-
与静态库不同的是 动态库在链接成功之后,还需要加载动态库到内存中,编译与加载是两个不同的动作
- 编译器在编译时并没有将动态库中的函数拷贝到可执行程序中,只是记录动态库的名字
- 在程序运行调用时,则需要将动态库加载到内存中
- 动态库默认加载动态库的路径与链接动态库的默认路径是相同的,都是 /lib 与 /usr/lib
- 当默认路径下没有时,则会到 LD_LIBRARY_PATH 环境变量下去找
- 可以通过 LD_LIBRARY_PATH 来设置动态库的路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:自己库所在的路径