一、Linux 动静态库的核心概念
库是编译好的可重用代码集合,Linux 下分为静态库和动态库,核心区别在于「代码融入可执行文件的时机」:
| 特性 | 静态库(.a) | 动态库(.so,Shared Object) |
|---|---|---|
| 编译阶段 | 完整拷贝库代码到可执行文件 | 仅记录库的引用(不拷贝代码) |
| 运行阶段 | 不依赖库文件,独立运行 | 需加载库文件(依赖.so 存在) |
| 可执行文件大小 | 较大(冗余拷贝) | 较小(共享代码) |
| 库更新 | 需重新编译可执行文件 | 仅替换.so 即可(接口不变时) |
| 内存占用 | 多程序使用时重复加载 | 多程序共享一份,节省内存 |
二、准备示例代码
先编写基础代码作为库的实现,后续基于此制作动静态库:
math.h(头文件,对外暴露接口):
#ifndef MATH_H
#define MATH_H
int add(int a, int b); // 加法
int mul(int a, int b); // 乘法
#endif
math.c(库的实现代码):
#include "math.h"
int add(int a, int b) {
return a + b;
}
int mul(int a, int b) {
return a * b;
}
main.c(测试程序,调用库接口):
#include <stdio.h>
#include "math.h"
int main() {
printf("3+5=%d\n", add(3,5));
printf("3*5=%d\n", mul(3,5));
return 0;
}
三、静态库(.a)的制作与使用
1. 制作静态库
步骤:编译生成目标文件(.o)→ 打包为静态库(.a)。
# 1. 编译math.c为目标文件(-c:只编译不链接,-o指定输出)
gcc -c math.c -o math.o
# 2. 用ar工具打包为静态库(命名规范:libxxx.a)
# ar参数:r(替换已有文件)、c(创建库)、s(建立索引,加速链接)
ar rcs libmath.a math.o
执行后生成 libmath.a,即静态库文件。
2. 使用静态库
编译测试程序时,指定「库路径」和「库名」:
# -L. :指定库所在路径(. 表示当前目录)
# -lmath:链接libmath.a(自动省略lib和.a,仅保留math)
gcc main.c -o main_static -L. -lmath
# 运行程序(无需依赖外部库,直接执行)
./main_static
# 输出:
# 3+5=8
# 3*5=15
下载C语言静态库
yum install glibc-static libstdc++-static -y
使用C语言静态库编译代码
gcc main.c -o main_static -L. -static
四、动态库(.so)的制作与使用
1. 制作动态库
步骤:编译生成「位置无关目标文件」→ 链接为动态库(.so)。
# 1. 编译为位置无关目标文件(-fPIC:生成位置无关代码,动态库必需)
gcc -c -fPIC math.c -o math.o
# 2. 链接为动态库(-shared:指定生成共享库,命名规范:libxxx.so)
gcc -shared -o libmath.so math.o
执行后生成 libmath.so,即动态库文件。
2. 使用动态库
(1)编译测试程序
# 编译命令和静态库类似(-lmath自动匹配libmath.so)
gcc main.c -o main_shared -L. -lmath
(2)运行动态库程序(关键:解决库加载路径)
直接运行会报错(系统默认只搜索 /lib、/usr/lib 等路径):
./main_shared
# 报错:error while loading shared libraries: libmath.so: cannot open shared object file: No such file or directory
解决方法(3 种):
方法 1:临时设置环境变量(终端关闭后失效)
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH # 把当前目录加入库搜索路径
./main_shared # 正常运行
方法 2:永久设置(需管理员权限)
#include <stdio.h>
#include "math.h"
int main() {
printf("3+5=%d\n", add(3,5));
printf("3*5=%d\n", mul(3,5));
return 0;
}
方法 3:编译时指定运行时库路径(推荐)编译时通过 -Wl,-rpath=路径 硬编码库路径到可执行文件:
gcc main.c -o main_shared -L. -lmath -Wl,-rpath=./
./main_shared # 直接运行,无需改环境变量
五、关键补充
- 库命名规范:必须以
lib开头,后缀为.a(静态)或.so(动态),否则-lxxx无法匹配。 - 查看动态库依赖:用
ldd命令检查可执行文件依赖的动态库:ldd main_shared # 输出示例(可见libmath.so的路径): # libmath.so => ./libmath.so (0x00007fxxxxxx) # libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fxxxxxx) - 动静态库二选一:若同一目录下同时有
libmath.a和libmath.so,gcc优先链接动态库;强制链接静态库需加-static:gcc main.c -o main_static_force -L. -lmath -static
六、总结
- 静态库:编译嵌入,独立运行,体积大,更新需重编;
- 动态库:运行加载,共享代码,体积小,更新灵活;
- 制作核心:静态库用
ar打包,动态库需-fPIC+-shared; - 使用核心:
-L指定路径,-l指定库名,动态库需解决加载路径。
3131

被折叠的 条评论
为什么被折叠?



