目录

1. 引言

2. 什么是库

3. 静态库(.a)

3.1 静态库的特点

3.2 制作静态库

3.3 使用静态库

3.4 静态链接的过程

4. 静态库的优缺点总结

5. 扩展:静态链接与 -static 选项

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:实现自定义的带缓冲文件操作(mfopenmfwritemfflushmfclose)。

  • my_string.h / my_string.c:实现一个 my_strlen 函数。

步骤:

  1. 编译为目标文件(.o

    bash

    gcc -c my_stdio.c my_string.c

    生成 my_stdio.o 和 my_string.o

  2. 使用 ar 工具打包为静态库

    bash

    ar -rc libmystdio.a my_stdio.o my_string.o
    • ar:GNU归档工具。

    • -r:替换或添加文件到库中。

    • -c:创建库(不显示提示)。

  3. 查看库内容

    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
  4. 提供头文件和库(供用户使用)
    通常将头文件放入 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. 小结

本文介绍了静态库的概念、制作流程、使用方法以及优缺点。静态库适合小型工具或对依赖有严格控制的场景。下一篇我们将讨论动态库,它能够有效解决静态库的空间浪费问题。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐