
🎬 个人主页 :艾莉丝努力练剑
❄专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》
《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平
🎬 艾莉丝的简介:

文章目录
- 核心考点总览(必记)
- [1 ~> 源码→可执行文件(四个核心步骤,必考)](#1 ~> 源码→可执行文件(四个核心步骤,必考))
-
- [1.1 预处理(Preprocessing)](#1.1 预处理(Preprocessing))
- [1.2 编译(Compilation)](#1.2 编译(Compilation))
- [1.3 汇编(Assembly)](#1.3 汇编(Assembly))
- [1.4 链接(Linking)(核心,必考)](#1.4 链接(Linking)(核心,必考))
- [2 ~> 目标文件(.o)深度解析(面试高频)](#2 ~> 目标文件(.o)深度解析(面试高频))
-
- [2.1 .o文件4大核心特性(必考)](#2.1 .o文件4大核心特性(必考))
- [2.2 符号表解析(readelf -s,必练)](#2.2 符号表解析(readelf -s,必练))
- [2.3 反汇编与重定位表(理解重定位核心)](#2.3 反汇编与重定位表(理解重定位核心))
- [3 ~> ELF文件(统一底层格式,必考)](#3 ~> ELF文件(统一底层格式,必考))
-
- [3.1 ELF的四种类型(必考,表格干货)](#3.1 ELF的四种类型(必考,表格干货))
- [3.2 ELF整体结构(四个部分,必记)](#3.2 ELF整体结构(四个部分,必记))
- [4 ~> 静态库(.a):原理 + 实操 + 考点](#4 ~> 静态库(.a):原理 + 实操 + 考点)
-
- [4.1 静态库制作(实操,必练)](#4.1 静态库制作(实操,必练))
- [4.2 静态库使用(链接,实操)](#4.2 静态库使用(链接,实操))
- [4.3 静态库核心特性(考点)](#4.3 静态库核心特性(考点))
- [5 ~> 动态库(.so):原理 + 实操 + 加载机制(难点)](#5 ~> 动态库(.so):原理 + 实操 + 加载机制(难点))
-
- [5.1 动态库制作(实操,必练,重点)](#5.1 动态库制作(实操,必练,重点))
- [5.2 动态库使用(链接 + 运行,实操,易错点)](#5.2 动态库使用(链接 + 运行,实操,易错点))
- [5.3 动态链接过程 + GOT / PLT(难点,必考)](#5.3 动态链接过程 + GOT / PLT(难点,必考))
- [5.4 动态库核心特性(考点)](#5.4 动态库核心特性(考点))
- [6 ~> 动静态库对比 + 工程选型(大厂场景题,必考)](#6 ~> 动静态库对比 + 工程选型(大厂场景题,必考))
-
- [6.1 核心对比(干货表格,无冗余)](#6.1 核心对比(干货表格,无冗余))
- [6.2 工程选型(标准答案,大厂认可)](#6.2 工程选型(标准答案,大厂认可))
- [7 ~> 高频面试题(含标准答案,必考)](#7 ~> 高频面试题(含标准答案,必考))
- [8 ~> 工程实践:动静态库常见问题排查(干货实操)](#8 ~> 工程实践:动静态库常见问题排查(干货实操))
- [9 ~> 核心总结(必记,快速复盘)](#9 ~> 核心总结(必记,快速复盘))
- 思维导图
- 结尾

核心考点总览(必记)
-
源码→可执行文件4步骤:预处理→编译→汇编→链接(核心:符号解析、地址重定位)
-
目标文件(.o):ELF可重定位文件,符号表、重定位表是核心
-
ELF4种类型:REL(.o)、EXEC(可执行)、DYN(.so)、CORE(核心转储)
-
静态库(.a):.o归档包,静态链接,可独立运行;动态库(.so):PIC编译,动态链接,多进程共享
-
高频面试题+实操命令+问题排查,全程无冗余,知识点全覆盖
1 ~> 源码→可执行文件(四个核心步骤,必考)
核心结论:所有.c/.cpp源码生成可执行文件,必须经过4步,前3步针对单个源码,第4步关联所有依赖。

1.1 预处理(Preprocessing)
-
核心作用:纯文本操作(无语法检查),完成注释删除、宏替换、#include头文件插入、条件编译、行号添加
-
输入/输出:.c文件 → .i文件(C语言)/.ii文件(C++)
-
实操命令:gcc -E test.c -o test.i (-E:仅执行预处理)
-
关键考点:#define与typedef区别(必考)
-
#define:预处理阶段,纯文本替换,无语法/类型检查,作用域到#undef或文件结束,可替换常量/函数片段 -
typedef:编译阶段,类型定义,有语法/类型检查,作用域遵循C语言规则,仅用于类型别名
-
1.2 编译(Compilation)
-
核心作用:语法检查、语义分析、代码优化,将高级语言→汇编语言
-
输入/输出:.i文件 → .s文件(汇编文件,文本格式)
-
实操命令:gcc -S test.i -o test.s (-S:大写,仅到编译阶段)
-
关键考点:语法错误、语义错误,均在本阶段检测(预处理不检测任何错误)
1.3 汇编(Assembly)
-
核心作用:汇编指令→机器指令,按ELF格式封装,生成目标文件
-
输入/输出:.s文件 → .o文件(目标文件,二进制格式,ELF-REL类型)
-
实操命令:gcc -c test.s -o test.o (-c:仅到汇编阶段)
-
辅助命令:objdump -d test.o (反汇编,查看机器指令);file test.o(验证ELF-REL类型)
-
关键考点:.o文件无法直接运行的原因(1、 地址是相对偏移量,未重定位;2、 依赖未解决)
1.4 链接(Linking)(核心,必考)
-
核心作用:完成2个核心任务(缺一不可),生成可执行文件(ELF-EXEC类型)
-
符号解析:关联未定义符号与对应定义(如printf来自C标准库,run来自code.o),未找到则报链接错误
-
地址重定位:合并所有.o文件的对应节,分配绝对内存地址,修正符号引用地址(相对→绝对)
-
-
输入/输出:多个.o文件+库文件(.a/.so) → 可执行文件(无固定后缀)
-
实操命令:gcc test.o -o test (默认动态链接);gcc -static test.o -o test(静态链接)
-
关键考点:链接错误排查(undefined reference to xxx)
-
排查1:是否遗漏编译相关.o文件(如未编译code.o,导致run函数未定义)
-
排查2:是否链接所需库文件(如数学库-lm,解决sin函数未定义)
-
排查3:库文件路径是否正确(用-L参数指定库路径)
-
-
链接方式区别(铺垫动静态库)
-
静态链接:复制静态库代码到可执行文件,体积大,可独立运行,不依赖外部库
-
动态链接:仅记录动态库依赖信息,体积小,运行时加载.so,多进程共享
-
2 ~> 目标文件(.o)深度解析(面试高频)
核心定位:汇编输出,链接输入,动静态库的基础单元(.a是.o归档,.so是PIC编译的.o集合)
2.1 .o文件4大核心特性(必考)
-
可重定位性:地址为相对偏移量(从0开始),未确定绝对地址,需链接阶段重定位
-
模块化隔离:每个.c→独立.o,互不影响,仅通过符号引用关联,修改单个.c仅需重新编译对应.o(提升编译效率)
-
含符号表(.symtab节):链接器符号解析、地址重定位的核心依据,记录3类符号
-
ELF-REL类型:与可执行文件、动态库格式统一(均为ELF),仅类型不同
2.2 符号表解析(readelf -s,必练)
实操案例:hello.c(引用run)、code.c(定义run),编译为hello.o、code.o,查看符号表
bash
gcc -c hello.c -o hello.o; gcc -c code.c -o code.o
readelf -s hello.o # 查看hello.o符号表
readelf -s code.o # 查看code.o符号表
-
符号表核心字段:Num(索引)、Value(地址,UND为0)、Type(FUNC/OBJECT)、Bind(LOCAL/GLOBAL)、Ndx(节索引)、Name(符号名)
-
3类核心符号(必考)
-
定义符号:当前.o中定义,Ndx为.text/.data,Bind=GLOBAL,Value为非0偏移量(如code.o的run,hello.o的main)
-
未定义符号:当前.o引用但未定义,Ndx=UND,Value=0,需链接阶段解决(如hello.o的run,所有.o的printf)
-
局部符号:仅当前.o可见,Bind=LOCAL,无法被其他.o引用(如static修饰的函数/变量)
-
-
关键考点:static修饰函数无法被其他文件引用的原因(Bind=LOCAL,仅当前.o可见)
2.3 反汇编与重定位表(理解重定位核心)
-
反汇编(objdump -d):查看未重定位地址(callq指令地址为0)
objdump -d hello.o # 查看main函数,callq printf/run地址均为0x00000000
-
重定位表(.rel.text/.rel.data,readelf -r):记录需重定位的符号、地址偏移量,供链接器修正
readelf -r hello.o # 查看重定位表,Offset为需修正地址,Sym.Name为目标符号(printf/run)
-
核心逻辑:编译器无法确定UND符号地址,暂设为0;链接器通过重定位表,替换为绝对地址,完成重定位
3 ~> ELF文件(统一底层格式,必考)

核心结论:Linux下,.o、可执行文件、.so均为ELF格式,仅类型不同;.a是.o归档包,非独立ELF类型。

3.1 ELF的四种类型(必考,表格干货)
| ELF类型 | 后缀名 | 核心用途 | 关键特性 |
|---|---|---|---|
| REL(可重定位文件) | .o | 链接输入,动静态库基础单元 | 可重定位,含UND符号,无程序头表,有节头表,无法直接运行 |
| EXEC(可执行文件) | 无固定后缀(如test) | 程序运行最终形态,直接执行 | 地址确定,无UND符号,有程序头表+节头表,可直接运行 |
| DYN(共享目标文件) | .so(动态库) | 动态链接,运行时加载,多进程共享 | 可重定位+可共享,PIC技术,有程序头表+节头表,多进程共享 |
| CORE(内核转储文件) | core | 程序崩溃时生成,调试崩溃原因 | 保存内存/寄存器/调用栈,供gdb调试 |
必考考点: .a为何不属于独立ELF类型?(.a是ar命令打包的多个.o归档包,本质是.o集合,非单一ELF文件,file libtest.a输出为ar archive)
bash
ar -rcs libtest.a hello.o code.o # 制作静态库,验证文件类型
file libtest.a # 输出:current ar archive(非ELF)

3.2 ELF整体结构(四个部分,必记)
结构顺序(偏移量从0开始):ELF头 → 程序头表 → 节 → 节头表
-
ELF头(ELF Header):ELF"身份证",64位固定64字节,含魔数、文件类型、架构、入口地址、程序头表/节头表偏移量
-
必考:ELF魔数(0x7f 45 4c 46);REL类型e_phoff=0(无程序头表)
-
实操命令:readelf -h 文件名(查看ELF头)
-
-
程序头表:仅EXEC、DYN有,供操作系统加载,描述段(Segment)信息(多个同属性节合并为段)
-
节(Section):内容载体,核心节(必考)
-
代码相关:.text(代码段,只读可执行)、.init(初始化代码)
-
数据相关:.data(已初始化数据)、.bss(未初始化数据,不占文件空间)
-
符号/重定位相关:.symtab(符号表)、.rel.text(代码段重定位表)
-
-
节头表:所有ELF都有(除非strip剥离),描述所有节的名称、大小、偏移量、属性,供链接器使用。
4 ~> 静态库(.a):原理 + 实操 + 考点
核心定义: 通过ar命令将多个.o文件打包生成的归档包,静态链接时,代码被复制到可执行文件。
4.1 静态库制作(实操,必练)
bash
# 1、编译生成多个.o文件
gcc -c hello.c -o hello.o; gcc -c code.c -o code.o
# 2、打包生成静态库(命名规范:libxxx.a)
ar -rcs libtest.a hello.o code.o # -r:替换/添加.o;-c:创建库;-s:生成索引(关键,不可少)
# 3、查看静态库内容(验证是否包含目标.o)
ar -t libtest.a # 列出静态库中的.o文件
ar -x libtest.a # 解压静态库,查看所有.o文件
4.2 静态库使用(链接,实操)
bash
# 方式1:指定库路径、库名称(-L:库路径;-l:库名,省略lib和.a)
gcc main.c -o main -L./ -ltest # ./是静态库所在路径,test是libtest.a的库名
# 方式2:直接链接静态库文件
gcc main.c -o main libtest.a
# 方式3:静态链接(强制使用静态库,不使用动态库)
gcc -static main.c -o main -L./ -ltest
4.3 静态库核心特性(考点)
-
链接特性:静态链接,将所需代码复制到可执行文件,可执行文件体积大
-
运行特性:不依赖外部库,可独立运行,移植性强(复制可执行文件即可运行)
-
缺点:可执行文件体积大;静态库更新后,需重新编译链接所有依赖该库的程序;浪费内存(多个进程运行,各自有一份库代码)
-
关键考点:静态链接与动态链接的核心差异(铺垫后续对比)
5 ~> 动态库(.so):原理 + 实操 + 加载机制(难点)
核心定义:经过-fPIC(地址无关代码)编译的.o文件,链接为共享目标文件,动态链接时不复制代码,仅记录依赖,运行时加载
5.1 动态库制作(实操,必练,重点)
bash
# 1、编译生成PIC格式的.o文件(-fPIC:地址无关代码,关键,不可少)
gcc -c -fPIC hello.c -o hello.o; gcc -c -fPIC code.c -o code.o
# 2、生成动态库(命名规范:libxxx.so,可加版本号,如libtest.so.1)
gcc -shared -fPIC -o libtest.so hello.o code.o # -shared:生成动态库
# 3、查看动态库依赖(验证动态库合法性)
readelf -d libtest.so # 查看动态库的依赖信息
ldd libtest.so # 查看动态库依赖的其他库
关键考点:-fPIC的作用(必考):生成地址无关代码,使动态库可被加载到任意内存地址,支持多进程共享,避免地址冲突
5.2 动态库使用(链接 + 运行,实操,易错点)
bash
# 1、动态链接(与静态库链接语法一致,默认优先动态链接)
gcc main.c -o main -L./ -ltest # -L:动态库路径;-l:库名
# 2、运行可执行文件(需让系统找到动态库,3种方式,必记)
# 方式1:临时生效,设置LD_LIBRARY_PATH(当前终端有效)
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH # ./是动态库所在路径
./main
# 方式2:永久生效,将动态库路径写入/etc/ld.so.conf,更新缓存
echo "./" >> /etc/ld.so.conf
ldconfig # 更新动态库缓存,无需重启
# 方式3:将动态库复制到系统默认库路径(/lib64、/usr/lib64)
cp libtest.so /usr/lib64
./main
5.3 动态链接过程 + GOT / PLT(难点,必考)
-
动态链接完整过程(分两步)
1、编译链接阶段:仅记录动态库依赖信息(库名、路径),不复制代码,生成可执行文件(含GOT、PLT)
2、程序运行阶段:动态链接器(ld-linux.so)加载所需动态库,完成符号解析、地址重定位,程序正常执行
-
GOT(全局偏移量表)+ PLT(过程链接表)(核心作用:延迟绑定,优化性能)
-
GOT:存储动态符号的最终绝对地址,初始为空,第一次调用符号时填充
-
PLT:存储跳转指令,第一次调用符号时,跳转至动态链接器,解析符号地址并填充到GOT;后续调用直接跳转至GOT中的地址,无需重复解析
-
必考:延迟绑定的优势(减少程序启动时间,避免加载未使用的符号,提升性能)
-

5.4 动态库核心特性(考点)
-
链接特性:动态链接,不复制代码,可执行文件体积小,仅记录依赖
-
运行特性:依赖动态库,需系统能找到.so文件;多进程共享同一动态库代码(节省内存)
-
优点:可执行文件体积小;动态库更新后,无需重新编译链接程序(仅需替换.so);多进程共享,节省内存
-
缺点:移植性弱(需携带对应.so文件);动态库缺失/版本不匹配,程序无法运行
6 ~> 动静态库对比 + 工程选型(大厂场景题,必考)

6.1 核心对比(干货表格,无冗余)
| 对比维度 | 静态库(.a) | 动态库(.so) |
|---|---|---|
| 本质 | 多个.o文件的归档包 | PIC编译的共享目标文件 |
| 链接方式 | 静态链接,复制代码到可执行文件 | 动态链接,仅记录依赖,运行时加载 |
| 可执行文件体积 | 大 | 小 |
| 运行依赖 | 无,可独立运行 | 依赖.so文件,需系统可找到 |
| 内存占用 | 大,多进程各自有一份代码 | 小,多进程共享代码 |
| 更新维护 | 麻烦,更新后需重新编译链接 | 简单,替换.so即可,无需重新编译 |
| 移植性 | 强,仅需复制可执行文件 | 弱,需携带对应.so文件 |

6.2 工程选型(标准答案,大厂认可)
-
选静态库的场景:程序需独立运行(如工具类程序、嵌入式设备)、移植性要求高、库体积小、无需频繁更新
-
选动态库的场景:多进程运行(如服务器程序)、库体积大、需频繁更新、内存资源紧张、多个程序共用同一库
-
补充:实际开发中,动态库更常用(节省内存、便于更新);静态库多用于小型工具、嵌入式、需独立部署的场景
7 ~> 高频面试题(含标准答案,必考)
- Q:Linux下,静态库(.a)与动态库(.so)的核心差异是什么?工程中如何选型?
- A:核心差异(见六、6.1表格,重点说链接方式、运行依赖、内存占用);选型(见六、6.2,分场景表述)
- Q:Linux下,.c源码到可执行文件的完整流程是什么?链接阶段的核心任务有两个,分别是什么?
- A:流程:预处理→编译→汇编→链接;链接核心任务:1、 符号解析(关联UND符号与定义);2、 地址重定位(相对地址→绝对地址)
- Q:ELF文件有哪4种类型?Linux下静态库(.a)为何不属于独立ELF类型?
- A:4种类型:REL(.o)、EXEC(可执行)、DYN(.so)、CORE(core);.a是ar打包的多个.o归档包,本质是.o集合,非单一ELF文件,故不属于独立ELF类型
- Q:Linux动态链接的完整过程?GOT与PLT的作用是什么?延迟绑定的优势是什么?
- A:动态链接过程:编译链接(记录依赖)→ 运行加载(动态链接器加载.so,完成解析重定位);GOT存储符号最终地址,PLT跳转指令;延迟绑定优势:减少启动时间,避免加载未使用符号,提升性能
- Q:Linux下动态库加载失败的3种常见原因,及对应的排查命令(至少说出2种命令)?
- A:原因1:动态库缺失;原因2:动态库路径错误(系统找不到);原因3:动态库版本不匹配;排查命令:ldd 可执行文件(查看依赖)、readelf -d 可执行文件(查看依赖信息)、echo $LD_LIBRARY_PATH(查看环境变量)
- Q:Linux中,多个进程如何共享同一个动态库?静态链接会导致什么问题?
- A:多进程共享:动态库采用PIC地址无关代码,加载到内存后,多个进程通过页表映射共享同一物理内存中的库代码;静态链接问题:可执行文件体积大、多进程浪费内存、库更新后需重新编译链接
8 ~> 工程实践:动静态库常见问题排查(干货实操)
1、问题1:链接错误(undefined reference to xxx)
- 排查:1、 检查是否遗漏编译对应.o文件;2、 检查是否链接所需库(如-lm);3、 检查库路径(-L参数);4、 检查符号是否为LOCAL(static修饰,无法引用)。
2、问题2:动态库加载失败(error while loading shared libraries: libxxx.so: cannot open shared object file)
- 排查:1、 ldd 可执行文件,确认.so是否缺失;2、 检查LD_LIBRARY_PATH是否包含.so路径;3、 检查/etc/ld.so.conf是否有路径,执行ldconfig更新缓存;4、 检查.so版本是否匹配。
3、问题3:静态库更新后,程序运行结果未变化
- 排查:静态链接需重新编译链接程序(静态库代码已复制到可执行文件,更新.a后,需重新gcc编译链接,生成新的可执行文件)。
4、问题4:无法查看.o/.so符号表、重定位表
- 排查:文件被strip命令剥离了符号表/节头表,重新编译生成(不执行strip),或重新制作库文件。
9 ~> 核心总结(必记,快速复盘)
-
1、四步骤:预处理(.c→.i)、编译(.i→.s)、汇编(.s→.o)、链接(.o+库→可执行);
-
2、三类文件:.o(ELF-REL,符号表/重定位表)、.a(.o归档,静态链接)、.so(ELF-DYN,PIC,动态链接);
-
3、两个核心:链接的2个任务(符号解析、地址重定位);GOT/PLT(延迟绑定,优化性能);
-
4、一个选型原则:按移植性、内存、更新频率、运行场景,选择静态库 / 动态库;
-
5、 关键命令:readelf(查看ELF信息)、objdump(反汇编)、ar(静态库操作)、ldd(动态库依赖)、gcc(编译链接)。
思维导图
bash
Linux动静态库与可执行文件 (全干货.必考)
├── 核心考点总览
│ ├── 源码→可执行文件4步骤:预处理→编译→汇编→链接
│ │ └── 链接核心:符号解析、地址重定位
│ ├── 目标文件(.o):ELF可重定位文件,核心是符号表、重定位表
│ ├── ELF4种类型
│ │ ├── REL(.o)
│ │ ├── EXEC(可执行)
│ │ ├── DYN(.so)
│ │ └── CORE(核心转储)
│ ├── 静态库(.a):.o归档包,静态链接,可独立运行
│ ├── 动态库(.so):PIC编译,动态链接,多进程共享
│ └── 核心包含:实操命令+高频面试题+问题排查
├── 源码→可执行文件
│ ├── 核心结论:前3步处理单个源码,第4步关联所有依赖
│ ├── 预处理(Preprocessing)
│ │ ├── 核心作用:删注释、宏替换、头文件插入、条件编译、行号添加
│ │ ├── 输入/输出:.c→.i/.ii
│ │ ├── 实操命令:gcc -E test.c -o test.i
│ │ └── 考点:#define(预处理) vs typedef(编译)
│ ├── 编译(Compilation)
│ │ ├── 核心作用:语法/语义检查、优化,高级语言→汇编语言
│ │ ├── 输入/输出:.i→.s
│ │ ├── 实操命令:gcc -S test.i -o test.s
│ │ └── 考点:语法/语义错误在此阶段检测
│ ├── 汇编(Assembly)
│ │ ├── 核心作用:汇编指令→机器指令,生成ELF-REL类型目标文件
│ │ ├── 输入/输出:.s→.o
│ │ ├── 实操命令:gcc -c test.s -o test.o
│ │ ├── 辅助命令:objdump -d、file
│ │ └── 考点:.o无法直接运行的原因(相对地址、依赖未解决)
│ └── 链接(Linking,核心)
│ ├── 核心任务1:符号解析(关联未定义符号与定义)
│ ├── 核心任务2:地址重定位(相对地址→绝对地址,合并.o节)
│ ├── 输入/输出:多个.o+库文件→可执行文件(ELF-EXEC)
│ ├── 实操命令:gcc test.o -o test、gcc -static
│ ├── 考点:链接错误排查(undefined reference)
│ └── 链接方式区别:静态(复制代码) vs 动态(记录依赖)
├── 目标文件(.o)深度解析(面试高频)
│ ├── 核心定位:汇编输出、链接输入,动静态库的基础单元
│ ├── .o文件4大核心特性(必考)
│ │ ├── 可重定位性:地址从0开始,需链接重定位
│ │ ├── 模块化隔离:一个.c→一个.o,修改仅重编译对应.o
│ │ ├── 含符号表(.symtab节):链接核心依据,记录3类符号
│ │ └── ELF-REL类型:与其他ELF文件格式统一,仅类型不同
│ ├── 符号表解析(readelf -s,必练)
│ │ ├── 实操命令:readelf -s 目标.o
│ │ ├── 核心字段:Num、Value、Type、Bind、Ndx、Name
│ │ └── 3类核心符号:定义符号、未定义符号、局部符号
│ └── 反汇编与重定位表
│ ├── 反汇编:objdump -d 目标.o
│ ├── 重定位表:readelf -r 目标.o
│ └── 核心逻辑:编译器暂设UND符号地址为0,链接器修正为绝对地址
├── ELF文件(统一底层格式,必考)
│ ├── 核心结论:.o、可执行文件、.so均为ELF,.a是.o归档(非ELF)
│ ├── ELF4种类型(必考)
│ │ ├── REL(.o):链接输入,可重定位,无程序头表
│ │ ├── EXEC(可执行):直接运行,地址固定,有程序头表+节头表
│ │ ├── DYN(.so):动态库,PIC技术,可共享,有程序头表+节头表
│ │ ├── CORE(core):崩溃转储,调试用
│ │ └── 考点:.a非独立ELF类型(ar打包.o集合)
│ └── ELF整体结构(4部分,必记)
│ ├── 结构顺序:ELF头→程序头表→节→节头表
│ ├── ELF头:魔数(0x7f 45 4c 46)、文件类型等
│ ├── 程序头表:仅EXEC/DYN有,供系统加载
│ ├── 核心节(必考)
│ │ ├── .text(代码)
│ │ ├── .data(已初始化数据)
│ │ ├── .bss(未初始化)
│ │ └── .symtab(符号表)
│ └── 节头表:所有ELF有,描述节信息
├── 静态库(.a):原理+实操+考点
│ ├── 核心定义:ar命令打包多个.o,静态链接时复制代码到可执行文件
│ ├── 静态库制作
│ │ ├── 步骤1:gcc -c 源码.c -o 目标.o
│ │ ├── 步骤2:ar -rcs libxxx.a 目标1.o 目标2.o
│ │ └── 辅助命令:ar -t(查看.o)、ar -x(解压)
│ ├── 静态库使用(实操)
│ │ ├── 方式1:gcc main.c -o main -L. -ltest
│ │ ├── 方式2:gcc main.c -o main libtest.a
│ │ └── 方式3:gcc -static(强制静态链接)
│ └── 核心特性(考点)
│ ├── 链接:复制代码,可执行文件体积大
│ ├── 运行:无依赖,可独立运行,移植性强
│ └── 缺点:体积大、更新需重编译、多进程浪费内存
├── 动态库(.so):原理+实操+加载机制(难点)
│ ├── 核心定义:-fPIC编译的.o,动态链接仅记录依赖,运行时加载
│ ├── 动态库制作(必练,重点)
│ │ ├── 步骤1:gcc -c -fPIC 源码.c -o 目标.o
│ │ ├── 步骤2:gcc -shared -fPIC -o libxxx.so 目标1.o 目标2.o
│ │ ├── 步骤3:readelf -d、ldd(查看依赖库)
│ │ └── 考点:-fPIC作用(地址无关代码)
│ ├── 动态库使用(实操,易错点)
│ │ ├── 动态链接:gcc main.c -o main -L. -ltest
│ │ └── 运行找.so的3种方式
│ │ ├── 方式1:export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH(临时)
│ │ ├── 方式2:写入/etc/ld.so.conf + ldconfig(永久)
│ │ └── 方式3:复制到/usr/lib64(系统默认路径)
│ ├── 动态链接过程+GOT/PLT(难点,必考)
│ │ ├── 动态链接2步:编译链接(记录依赖)→运行加载(解析重定位)
│ │ ├── GOT(全局偏移量表):存储符号最终地址,第一次调用填充
│ │ ├── PLT(过程链接表):跳转指令,第一次解析符号,后续直接跳GOT
│ │ └── 考点:延迟绑定优势(减少启动时间、避免加载未使用符号)
│ └── 核心特性(考点)
│ ├── 链接:不复制代码,可执行文件体积小
│ ├── 运行:依赖.so,多进程共享,节省内存
│ └── 缺点:移植性弱、.so缺失/版本不匹配无法运行
├── 动静态库对比+工程选型(大厂场景题,必考)
│ ├── 核心对比
│ │ ├── 本质:静态库(.o归档) vs 动态库(PIC共享文件)
│ │ ├── 链接方式:静态(复制代码) vs 动态(记录依赖)
│ │ ├── 体积:静态(大) vs 动态(小)
│ │ ├── 运行依赖:静态(无) vs 动态(需.so)
│ │ ├── 内存占用:静态(高) vs 动态(低)
│ │ ├── 更新维护:静态(麻烦,重编译) vs 动态(简单,换.so)
│ │ └── 移植性:静态(强) vs 动态(弱)
│ └── 工程选型(标准答案)
│ ├── 选静态库:独立运行、移植性高、库小、不频繁更新(嵌入式)
│ └── 选动态库:多进程、库大、频繁更新、内存紧张(服务器)
├── 高频面试题(含标准答案,必考)
│ ├── Q1:动静态库核心差异+工程选型?
│ ├── Q2:.c→可执行文件流程+链接核心任务?
│ ├── Q3:ELF4种类型+.a非ELF原因?
│ ├── Q4:动态链接过程+GOT/PLT作用+延迟绑定优势?
│ ├── Q5:动态库加载失败原因+排查命令?
│ └── Q6:多进程共享动态库方式+静态链接问题?
├── 工程实践:常见问题排查(干货实操)
│ ├── 问题1:链接错误(undefined reference)
│ ├── 问题2:动态库加载失败
│ ├── 问题3:静态库更新后程序不变
│ └── 问题4:无法查看符号表
└── 核心总结(必记,快速复盘)
├── 4步骤:预→编→汇→链
├── 3类文件:.o(ELF-REL)、.a(.o归档)、.so(ELF-DYN)
├── 2个核心:链接2任务、GOT/PLT延迟绑定
├── 1个选型原则:按移植性、内存、更新频率、场景选择
└── 关键命令:readelf、objdump、ar、ldd、gcc
结尾
uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!
往期回顾:
【Linux:文件】Linux 动静态库与可执行文件深度解析
🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა
