【 linux 】动静态库的制作

目录

[1. 认识动静态库](#1. 认识动静态库)

[2. 理解动静态库](#2. 理解动静态库)

[3. 动静态库的制作与对比](#3. 动静态库的制作与对比)

1.静态库的制作

[2. 动态库的制作](#2. 动态库的制作)

[3. 对比](#3. 对比)

4.认识ELF格式


1. 认识动静态库

本质上是一组预先编译好的代码、函数或资源的集合,供其他程序调用,以避免重复造轮子。根据链接时机加载方式 的不同,库主要分为 静态库动态库

静态库:在程序的编译链接阶段 ,链接器会将静态库中的代码完整复制并合并到最终的可执行文件中。linux/macOS中后缀是.a,windows中后缀是.lib

静态库的特点是**独立性强,**生成的可执行文件包含了所有依赖代码,运行时不需要外部库文件,部署方便。但是需要将代码完整复制一遍到可执行文件中更耗费资源,如果库进行更新的话所有的可执行文件都要重新编译链接非常不方便

动态库:在编译时 将代码复制到可执行文件中,仅记录引用信息。代码在程序运行时由操作系统动态加载到内存中。linux中后缀是.so,macOS中是.dylib,windows中是.dll

动态库更**节省空间,**多个进程可以共享内存中的同一份库代码,显著减少磁盘和内存占用。只要接口(ABI)兼容,替换库文件即可生效,无需重新编译主程序

2. 理解动静态库

所有的库本质上都是源文件对应的.o,库也是要被安装到系统中的,可以以C标准库举例,/lib64/libc.so.6动态库文件,是程序运行时真正加载的文件,/usr/lib64/libc.a静态库版本

不同发行版路径可能不同,可以用以下命令确认

复制代码
# 查看 libc 的实际路径
ldconfig -p | grep libc.so

# 或者直接查找
find /lib* /usr/lib* -name "libc.so*" 2>/dev/null

C标准库是操作系统的核心组件,在安装操作系统时就已经预装,它是系统启动和用户空间程序运行的先决条件

3. 动静态库的制作与对比

1.静态库的制作

静态库的本质就是打一个包,我们可以自己写两个头文件和源文件,定义为mystdio.h,mystring.h,mystdio.c,mystring.c

将.c文件编译生成.o文件,在将.o文件打包生成.a文件

复制代码
.PHONY: all clean

all: libmy.a

libmy.a: mystdio.o mystring.o
	ar rcs $@ $^

%.o: %.c
	gcc -c $< -o $@

clean:
	rm -f *.o libmy.a

目录结构是这样的

复制代码
project/
├── lib/                    ← 静态库目录
│   ├── include/            ← 头文件(对外接口)
│   │   ├── mystdio.h
│   │   └── mystring.h
│   ├── src/                ← 库源码(内部实现)
│   │   ├── mystdio.c
│   │   ├── mystring.c
│   │   └── Makefile        ← 只负责生成 libmy.a
│   └── libmy.a             ← 生成的静态库产物
│
└── app/                    ← 主程序目录
    ├── main.c              ← 主函数入口
    └── Makefile            ← 只负责编译 main.c 并链接 libmy.a

编译链接生成可执行文件:

gcc main.c -I ..lib/include -L ../lib -l my -o app

介绍一下这几个命令都是干什么的,打包时需要用到ar -rc命令,rc是replace and create,存在同名.o替换,不存在插入,.a不存在创建

-大写i是查找头文件,连接任何的非C/C++标注库都需要指明-L,-l,小写l后面是.a文件名(去掉lib)

2. 动态库的制作

动态库的制作和静态库类似,编译阶段 加上-fPIC命令产生位置无关码,gcc -c -fPIC *.c -o *.o

打包成库时 加上-shared生成共享库格式,gcc -shared *.o -o .so

主程序的命令和静态库相同,对于静态库来说链接器需要将.a文件代码拷贝到main.c中,对于动态库链接器记录依赖,根据路径实时加载.so到内存

3. 对比

gcc/g++默认使用动态库,想用静态库需要加上-static(只存在静态库可执行程序只能静态链接)

linux系统中默认安装的大部分库都是动态库

库:应用程序=1:n

4.认识ELF格式

动静态库,可执行程序,.o文件都是ELF格式,ELF格式主要有以下几部分

ELF Header记录文件特征,Program Header Table记录段(segment)的信息,Section Header Table记录节(Section)的信息

库形成可执行程序需要进行Section的合并 ,相同属性合并成一个段(segment),关于如何合并的信息存储在Program Header Table中,所有需要被加载到内存中执行的 ELF 文件(包括可执行文件和共享库)都有 Segment;而不需要加载的文件(如 .o 目标文件、静态库 .a)只有 Section,没有 Segment

实际过程

链接脚本(Linker Script)定义了 Output Section 的排列顺序和属性 → 链接器根据这些属性(R/W/X + ALLOC)将多个 Input Section 分配到不同的 Program Header 条目中 → 同时生成节头表和程序头表

没有 Segment 的文件,也没有 Program Header Table,可以执行readelf -l hello.o查看,可以用read -S hello.o读取Section Header节表头


相关推荐
songjxin1 小时前
Nginx 日志分析可视化面板
运维·nginx
专注VB编程开发20年2 小时前
安卓APP与服务器通讯技术,文件传输和文字消息收发
运维·服务器
顺风尿一寸2 小时前
深入Linux内核:mkdir系统调用的完整实现解析
linux
用户2367829801682 小时前
Linux free 命令深度解析:从内存监控到 OOM 排查的完整指南
linux
过期动态2 小时前
【LeetCode 热题 100】接雨水
java·数据结构·算法·leetcode·职场和发展
春日见2 小时前
5分钟入门强化学习之动态规划算法与实现
大数据·人工智能·python·算法·机器学习·计算机视觉
Agent手记2 小时前
电信运营商如何用AI实现携号转网自动处理?基于实在Agent的业务自动化落地与TARS大模型解析方案
运维·人工智能·ai·自动化
scx_link2 小时前
线性回归的总结:
算法·机器学习·线性回归
郝亚军2 小时前
IEEE 754 单精度浮点的SEM表示
开发语言·c++·算法