news 2026/10/12 3:58:23

【知识讲解】 Linux之动静态库的了解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【知识讲解】 Linux之动静态库的了解


目录

前言

Part1. 库的意义

Part2. 静态库制作、编译与发布

Part2.1. 静态库制作步骤

Part2.2. 使用静态库编译业务代码

Part2.3. 静态库的打包分发

Part2.4. Makefile 自动化构建静态库、一键打包发布

Part3. 动态库制作、编译、部署

Part3.1. 动态库制作

Part3.2. 编译业务程序链接动态库

Part3.3. 解决运行时找不到动态库的方案

Part3.4. 强制链接静态库

Part4. 静态库与动态库对比

Part5. 补充拓展

Part6. 结语


前言

Linux下对于动静态库的认识是非常重要的,接下来来跟随小编的视角来看看吧。


let's go!!!!!!!!


Part1. 库的意义

在工程开发中,我们会把可复用的功能封装成库,不需要每次都重新编译源码。


• 源码不需要对外交付,只需要交付头文件(.h,用于给用户声明函数) +库文件(.a / .so,存放编译好的机器指令)

•多个项目可以复用同一套库,大幅减少重复编译的成本

• 版本迭代时,只需要更新库文件,业务代码无需改动


补充:目标文件 .o 的价值:一个大型工程有上百个 .c 文件,如果只修改其中一个源码,只需要重新编译这一个文件生成 .o,其余目标文件可以直接复用,避免全量重新编译,节省编译时间。


编译链路:.c → 编译生成 .o(可重定位目标文件,ELF格式) → 链接 → 可执行程序 / 库


底层小知识:.o、静态库、动态库、可执行程序,全部都是ELF格式。ELF内部由大量的section(段)组成:代码段、数据段、只读段等;运行时操作系统会把多个section合并为segment(段分区),映射到进程的虚拟地址空间。


Part2. 静态库制作、编译与发布

静态库后缀命名规范:libxxx.a,比如我们示例库名字为 libmyc.a


Part2.1. 静态库制作步骤

1. 先把源码编译为目标文件 .o

# -c:只编译,不链接,生成 *.o gcc -c 1.c -o 1.o gcc -c 2.c -o 2.o


2. 使用 ar 工具打包多个 .o,归档成为静态库 .a

# ar -rc :r插入/替换,c创建归档文件 ar -rc libmyc.a 1.o 2.o


ar 本质就是一个归档工具,把一堆 .o 打包成一个文件,静态库本身就是一堆目标文件的压缩包,gcc链接的时候会把库里面用到的目标代码直接拷贝进最终的可执行文件。


Part2.2. 使用静态库编译业务代码

假设业务代码 main.c 需要调用我们静态库里面的函数。
编译链接语法:

gcc -o exe main.c -I ./include -L ./mylib -l myc


参数解释:
参数 作用
-I路径 指定头文件搜索路径,用来找到 .h
-L路径 指定库文件(.a/.so)的搜索路径
-lxxx 链接名为 libxxx.a / libxxx.so 的库,自动补全lib前缀和后缀


Part2.3. 静态库的打包分发

我们交付给用户的时候,不需要交付 .c 源码,只需要交付:

• include/:存放 .h 头文件(函数声明)

• mylib/:存放编译好的 libmyc.a 静态库


用户拿到之后,有两种方式使用头文件:

1. 编译时通过 -I 指定头文件目录

gcc -c main.c -I ./lib/include


2. 或者直接把头文件拷贝到系统标准头文件目录 /usr/include

cp lib/include/* /usr/include


库文件拷贝到系统库目录 /usr/lib

cp lib/mylib/libmyc.a /usr/lib


之后编译就可以简化,不需要写 -I -L,直接:

gcc -o exe main.c -l myc

Part2.4. Makefile 自动化构建静态库、一键打包发布

可以用Makefile自动化完成编译、打包、创建目录、打包压缩交付包

libmyc.a: 1.o 2.o ar -rc $@ $^ 1.o:1.c gcc -c $< -o $@

# 发布目标:自动创建目录,拷贝头文件、库,打包tar压缩包

.PHONY: output output: mkdir -p lib/include mkdir -p lib/mylib cp -f *.h lib/include cp -f libmyc.a lib/mylib tar -czf lib.tgz lib


执行make output,直接生成 lib.tgz,这个压缩包就可以发给别人使用。


静态库核心特点:链接的时候,代码直接复制进exe。一旦编译完成,后续静态库文件就算删除,程序依旧可以正常运行。


Part3. 动态库制作、编译、部署

动态库后缀:.so,命名示例 libmyc.so


动态库不会把代码拷贝进可执行文件,程序运行的时候,操作系统才去加载 .so,多个进程可以共享同一份动态库在内存中的副本,节省内存。


Part3.1. 动态库制作

1. 编译目标文件,必须带上 -fPIC,生成位置无关代码

gcc -fPIC -c 1.c -o 1.o gcc -fPIC -c 2.c -o 2.o


-fPIC:Position Independent Code 位置无关代码,生成的机器指令没有硬编码绝对地址,可以被加载到虚拟地址空间的任意位置,是动态库的核心。静态库不需要 -fPIC。


2. 使用 -shared 参数,把 .o 链接打包为动态库 .so

gcc -shared -o libmyc.so 1.o 2.o

Part3.2. 编译业务程序链接动态库

编译链接阶段语法和静态库几乎一模一样:

gcc -o exe main.c -I ./include -L ./mylib -l myc


这里有一个非常经典的坑:编译链接成功,但是运行的时候报错,找不到动态库!


原因:-L 只是编译阶段告诉gcc去哪里找库;程序运行阶段是操作系统去加载动态库,和gcc已经无关了,操作系统有自己一套动态库搜索路径。


Part3.3. 解决运行时找不到动态库的方案

方案1:临时环境变量 LD_LIBRARY_PATH

LD_LIBRARY_PATH 是Linux操作系统的动态库环境变量,操作系统运行程序的时候,会优先从这个变量记录的目录里面搜索 .so。

# 临时生效,当前终端窗口有效,关闭终端就失效 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xxx/lib/mylib ./exe


方案2:写入系统动态库配置文件(永久生效)

Linux系统动态链接器会读取 /etc/ld.so.conf.d/ 下面的配置文件

1. 在 /etc/ld.so.conf.d/ 新建一个配置文件,随便命名,例如 myconfig.conf,写入我们动态库的绝对路径
/home/xxx/lib/mylib

2.更新动态链接器缓存ldconfig
永久生效,所有用户、所有终端都可以找到这个动态库


方案3:直接拷贝动态库到系统标准库目录/usr/lib

cp libmyc.so /usr/lib ldconfig

Part3.4. 强制链接静态库

如果你本身系统同时存在 .a 和 .so,gcc默认优先链接动态库。
如果你想要强制编译的时候使用静态库,增加 -static 参数

gcc -o exe main.c -I ... -L ... -l myc -static

Part4. 静态库与动态库对比

特性静态库 .a动态库 .so
链接时期:编译链接阶段,代码拷贝进可执行文件编译阶段只记录符号,运行时操作系统加载


程序体积:可执行文件更大,包含库代码可执行文件更小


内存占用:每个进程都有一份独立的库代码副本,内存占用高内存中只加载一份,多进程共享,节省内存


更新方式:更新库,业务代码必须重新编译链接替换 .so 文件即可,不需要重新编译业务程序


依赖:编译完成后不再依赖原 .a 文件运行时必须保证 .so 存在,否则程序无法启动

工程选型:Linux后端服务绝大多数场景优先使用动态库;一些嵌入式、想要单文件交付、不想携带一堆so的场景会使用静态库。


Part5. 补充拓展

1. .o 可重定位目标文件:编译产物,还没有分配虚拟地址,等待链接器完成地址重定位

2. ELF 文件内部划分为很多 section:.text代码段、.data数据段、.rodata只读段、.bss未初始化数据段

3. 当程序被操作系统加载运行时,内核会把多个section合并成segment内存段,映射到进程独立的虚拟地址空间,这就是进程的内存布局。


Part6. 结语

这篇文章我们深入的知道了动静态库的相关知识,接下来,小编还会带来更多Linux相关的知识,敬请期待~

最后,祝大家可以:春风得意马蹄疾,一日看尽长安花!

最后的最后,要是觉得本文还可以的话,可以点点赞,关注小编一波,谢谢大家!~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 3:57:59

【学习记录】PCB与PCBA核心知识全解析:从设计到制造的关键细节

【学习记录】PCB与PCBA核心知识全解析&#xff1a;从设计到制造的关键细节 在硬件设计中&#xff0c;PCB和PCBA是绕不开的基础。本文在原有框架上补充关键细节&#xff0c;把从设计到制造的知识点串起来&#xff0c;涵盖PCB/PCBA区别、阻焊颜色、表面处理、基板、过孔、制造流程…

作者头像 李华
网站建设 2026/10/12 3:57:17

std1.97.1——iter模块总览

目录1. Iterator2. 三种迭代形式3. 实现Iterator4. for循环与IntoIterator5. 按引用迭代6. 适配器7. 惰性8. 无穷参考1. Iterator 本模块的核心与灵魂是Iterator Trait。Iterator的核心部分如下所示&#xff1a; trait Iterator {type Item;fn next(&mut self) -> Opti…

作者头像 李华
网站建设 2026/10/12 3:57:02

技术讨论内容如何快速整理?

上周连着面了三批候选人&#xff0c;现场要同步记履历细节、项目经历和沟通要点&#xff0c;手上敲键盘的速度永远追不上对方说话的节奏&#xff0c;中途好几次漏了关键信息&#xff0c;回头翻录音又要拖很久进度。 后来试着用不同的工具处理这类场景&#xff0c;慢慢摸出了一些…

作者头像 李华
网站建设 2026/10/12 3:55:50

30 秒做出「真人感」AI Vlog:从本地生成人物到成片,保姆级教程

最近刷短视频&#xff0c;你应该也注意到了&#xff1a;一批「真人日常」感的 vlog 正在刷屏——手持镜头轻微晃动、窗边的自然光、素颜感的淡妆。唯一的区别是&#xff0c;画面里的人并不存在。 对普通创作者来说&#xff0c;这类内容的门槛正在快速下降。只需要一张人物图加…

作者头像 李华
网站建设 2026/10/12 3:55:50

官网Demo开发实战:从“8+1”需求拆解到组件复用与性能优化

大概一个月前&#xff0c;我接到一个需求&#xff1a;给某公司的官网做一套Demo&#xff0c;需求方原话就是“实现官网demo&#xff08;81&#xff09;”。当时我第一反应是这活儿挺简单&#xff0c;8个页面加1个页面而已&#xff0c;撑死一周搞定。结果做到一半就发现&#xf…

作者头像 李华
网站建设 2026/10/12 3:55:48

卫星通信元器件产线导入真空回流炉的选型复盘

去年秋天&#xff0c;老周给我打了个电话。他在成都一家做卫星通信T/R组件的厂里管封装产线&#xff0c;语气里透着那种"设备又卡住了"的疲惫。他们刚接了一个星上用的功放模块订单&#xff0c;基板是氮化铝&#xff0c;芯片是GaN功放管&#xff0c;要求焊接空洞率压…

作者头像 李华