Linux动静态库与动静态链接

在Linux开发中,库是预编译的代码集合,供程序调用;链接则是将库代码与程序代码结合的过程。根据库的存储和链接方式,分为静态库( .a )和动态库( .so ),对应的链接方式为静态链接和动态链接。

一、基本概念
  1. 静态库(Static Library)
  • 以 .a 为后缀,是目标文件( .o )的归档包。
  • 静态链接:编译时,链接器会将静态库中被程序调用的代码完整复制到可执行文件中。
  • 特点:可执行文件独立运行,不依赖外部库;文件体积大;库更新后,程序需重新编译链接。
  1. 动态库(Shared Library)
  • 以 .so 为后缀(Shared Object),是可被多个程序共享的代码库。
  • 动态链接:编译时,链接器仅记录程序对动态库的引用(如库名、函数地址),不复制库代码;程序运行时,由动态链接器加载动态库到内存并完成链接。
  • 特点:可执行文件体积小;多个程序共享同一份动态库,节省内存;库更新后,无需重新编译程序(只要接口兼容)。
二、代码示例(C语言)

准备工作:编写库的源文件

创建两个文件, math.c (库实现)和 math.h (库头文件):

c 复制代码
  
// math.h 头文件
#ifndef MATH_H
#define MATH_H
int add(int a, int b);
int sub(int a, int b);
#endif
 
 
c
  
// math.c 库实现
#include "math.h"
int add(int a, int b) {
    return a + b;
}
int sub(int a, int b) {
    return a - b;
}
 
  1. 制作并使用静态库

步骤1:编译生成目标文件 .o

c 复制代码
bash
  
gcc -c math.c -o math.o  # -c 表示只编译不链接,生成目标文件
 

步骤2:打包生成静态库 .a

c 复制代码
bash
 
ar rcs libmath.a math.o  # ar是归档工具,rcs:创建、替换、索引

步骤3:编写主程序并静态链接

创建主程序 main.c :

c 复制代码
  
#include <stdio.h>
#include "math.h"
int main() {
    printf("3+2=%d\n", add(3, 2));
    printf("3-2=%d\n", sub(3, 2));
    return 0;
}
 

步骤4:编译主程序并链接静态库

c 复制代码
bash
 
gcc main.c -o main_static -L. -lmath  # -L. 指定库路径(当前目录),-lmath 链接libmath.a

步骤5:运行与验证

c 复制代码
bash
  
./main_static
 

输出:

plaintext

3+2=5

3-2=1

  • 验证静态链接:删除静态库 libmath.a ,程序仍可正常运行(代码已复制到可执行文件中)。
  1. 制作并使用动态库

步骤1:编译生成位置无关的目标文件 .o

c 复制代码
bash
  
gcc -c -fPIC math.c -o math.o  # -fPIC 生成位置无关代码,用于动态库
 

步骤2:生成动态库 .so

c 复制代码
bash
  
gcc -shared -o libmath.so math.o  # -shared 表示生成动态库
 

步骤3:编译主程序并动态链接

c 复制代码
bash
 
gcc main.c -o main_dynamic -L. -lmath  # 编译命令与静态链接一致,链接器自动优先找动态库

步骤4:运行与验证

直接运行可能报错(系统找不到动态库),需指定动态库路径:

bash

方式1:临时指定环境变量

export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH

./main_dynamic

方式2:将动态库复制到系统库路径(如/usr/lib)

cp libmath.so /usr/lib

./main_dynamic

输出与静态链接一致:

plaintext

3+2=5

3-2=1

  • 验证动态链接:删除动态库 libmath.so ,程序运行时会报错(依赖外部库)。
相关推荐
顺顺 尼5 小时前
linux 进程信号(上)
linux·c++·算法
niuTaylor6 小时前
飞腾 FT-2000/4 Ubuntu 内存卡 / NVMe SSD 系统制作完整指南
linux·服务器·人工智能·驱动开发·单片机
傲世仙尊7 小时前
信号量环形队列与线程池起步-把临界资源拆成很多份
linux
Huangjin007_7 小时前
【Linux 系统篇(二十五)】文件(二) 系统文件I/O详解
linux·运维·服务器
ShineWinsu8 小时前
对于ProtoBuffer:ProtoBuffer的介绍以及安装
linux·网络·google·协议·序列化·反序列化·protobuffer
FlightYe8 小时前
视界原理之2D视频(二):视频文件里有什么
android·linux·网络·c++·ffmpeg·音视频·aac
GeW10 小时前
从代码到共识:技术突围如何映照大国相处之道
linux
承渊政道11 小时前
Linux系统学习【进程信号详细解析——认识、产生、保存以及捕捉信号】
linux·学习·ubuntu·ssh·vs code·进程信号
硅基手札11 小时前
【linux内核专栏01】Linux 内核心智模型与设计哲学
linux·运维·驱动开发·开源软件
码完就睡11 小时前
Linux——socket网络编程
linux·运维·网络