目录
[1. 引言](#1. 引言)
[2. 什么是库](#2. 什么是库)
[3. 静态库(.a)](#3. 静态库(.a))
[3.1 静态库的特点](#3.1 静态库的特点)
[3.2 制作静态库](#3.2 制作静态库)
[3.3 使用静态库](#3.3 使用静态库)
[3.4 静态链接的过程](#3.4 静态链接的过程)
[4. 静态库的优缺点总结](#4. 静态库的优缺点总结)
[5. 扩展:静态链接与 -static 选项](#5. 扩展:静态链接与 -static 选项)
[6. 小结](#6. 小结)
1. 引言
在软件开发中,库(Library)是预先编写好的、可复用的二进制代码集合。使用库可以极大提高开发效率,避免重复造轮子。Linux环境下主要有两种库:静态库 (.a)和动态库 (.so)。本文将详细讲解静态库的特点、制作方法、使用方式及其背后的链接原理。
2. 什么是库
库本质上是一种可执行代码的二进制形式,可以被操作系统载入内存执行。根据链接方式的不同,分为:
| 类型 | Linux后缀 | Windows后缀 | 特点 |
|---|---|---|---|
| 静态库 | .a |
.lib |
编译链接时被整合进可执行文件,运行时不再依赖 |
| 动态库 | .so |
.dll |
运行时动态加载,多个程序可共享内存中的同一份库代码 |
系统中常见的库示例:
-
C标准库:
/lib64/libc-2.17.so(动态)和/lib64/libc.a(静态) -
C++标准库:
/usr/lib/gcc/.../libstdc++.a和libstdc++.so
3. 静态库(.a)
3.1 静态库的特点
-
在编译链接阶段,库中的代码会被复制到最终的可执行文件中。
-
生成的可执行文件不依赖静态库,可以独立运行。
-
缺点:可执行文件体积大;多个程序使用同一静态库时,内存中存在多份副本,浪费内存和磁盘空间。
-
优点:部署简单,无需考虑目标机器是否有对应的库。
3.2 制作静态库
我们以文档中的 my_stdio 和 my_string 模块为例:
源文件:
-
my_stdio.h/my_stdio.c:实现自定义的带缓冲文件操作(mfopen、mfwrite、mfflush、mfclose)。 -
my_string.h/my_string.c:实现一个my_strlen函数。
步骤:
-
编译为目标文件(
.o)bash
gcc -c my_stdio.c my_string.c生成
my_stdio.o和my_string.o。 -
使用
ar工具打包为静态库bash
ar -rc libmystdio.a my_stdio.o my_string.o-
ar:GNU归档工具。 -
-r:替换或添加文件到库中。 -
-c:创建库(不显示提示)。
-
-
查看库内容
bash
ar -tv libmystdio.a输出示例:
text
rw-rw-r-- 1000/1000 2848 Oct 29 14:35 my_stdio.o rw-rw-r-- 1000/1000 1272 Oct 29 14:35 my_string.o -
提供头文件和库 (供用户使用)
通常将头文件放入
include/,库文件放入lib/,并打包发布。
3.3 使用静态库
编写 main.c,调用库中的函数:
c
#include "my_stdio.h"
#include "my_string.h"
#include <stdio.h>
int main() {
const char *s = "abcdefg";
printf("%s: %d\n", s, my_strlen(s));
mFILE *fp = mfopen("/log.txt", "a");
if (fp == NULL) return 1;
mfwrite(s, my_strlen(s), fp);
mfclose(fp);
return 0;
}
编译命令:
bash
# 方式1:头文件与库文件在当前目录
gcc main.c -L. -lmystdio
# 方式2:指定头文件路径和库路径
gcc main.c -I ./include -L ./lib -lmystdio
选项说明:
-
-I:指定头文件搜索路径。 -
-L:指定库文件搜索路径。 -
-l:指定库名(去掉前缀lib和后缀.a,如libmystdio.a写为lmystdio)。
3.4 静态链接的过程
静态链接的本质:将多个 .o 文件(包括从静态库中提取的 .o)合并成一个可执行文件。链接器会进行符号解析 和地址重定位,修正函数调用和变量访问的地址。
使用 file 命令查看生成的可执行文件:
bash
file a.out
# 输出:ELF 64-bit LSB executable
删除 libmystdio.a 后,可执行文件仍可正常运行,因为代码已完整嵌入。
4. 静态库的优缺点总结
| 优点 | 缺点 |
|---|---|
| 部署简单,无依赖 | 生成文件大 |
| 加载速度快(无需运行时解析) | 内存占用高(多进程无法共享) |
| 不受库版本升级影响 | 库更新后需重新链接 |
5. 扩展:静态链接与 -static 选项
默认情况下,gcc 会优先使用动态库。若要强制使用静态库,可添加 -static 选项:
bash
gcc -static main.c -L. -lmystdio
此时生成的可执行文件体积会显著增大(因为C运行时库也被静态链接进去)。
6. 小结
本文介绍了静态库的概念、制作流程、使用方法以及优缺点。静态库适合小型工具或对依赖有严格控制的场景。下一篇我们将讨论动态库,它能够有效解决静态库的空间浪费问题。