静态链接
复习
- 重定位:把占位替换成真实地址
- 目标文件格式:符号表与分段
- 从源代码到可执行文件:链接这一步
TL;DR
- 静态链接把多个目标文件拼成一个可执行文件
- 它要合并各段、分配地址并完成重定位
- 链接后的程序自包含,不依赖外部库文件
- 代价是文件较大、库更新需要重新链接
正文
有了目标文件和重定位,就可以把它们“拼”成可执行文件了。这一步叫链接(linking),而“在生成可执行文件时就把一切确定好”的做法,叫静态链接(static linking)。
链接器做的事
链接器把多个目标文件(以及用到的库)合到一起,大致做这几件事:
- 合并同类段:把各个文件的代码段拼成一个大代码段,数据段同理
- 分配地址:给合并后的各段、各符号安排最终的内存位置
- 符号解析:把一个文件引用的外部名字,对应到另一个文件里提供的定义
- 重定位:把所有“待填地址”换成真实地址
做完这些,就得到了一个完整的可执行文件。
静态库:按需抽取
很多程序会用到标准库里的函数。一个静态库,其实就是一堆预先编译好的目标文件打包在一起。链接器链接时,会只把程序真正用到的那几个目标文件抽出来,接进可执行文件——不必把整个库都塞进去。
好处与代价
静态链接的结果是自包含的:可执行文件里已经包含了它需要的一切,运行时不再依赖外部库文件。好处是:
- 部署简单:拷过去就能跑,不怕缺库
- 运行独立:不担心库被改坏或版本不对
代价则是:
- 文件大:每个程序都自带一份库代码,重复占空间
- 内存浪费:多个程序运行时,各自带着同样的库副本
- 更新麻烦:库修了 bug,得把每个用它重新链接过的程序都重新链接
正是这些代价,催生了另一种思路:别在编译时就把库链进去,等运行时再说。 这就是下一章的动态链接。
思考题 1
静态链接大致要做哪几件事?
思考题 2
静态链接的程序“自包含”,有什么好处和坏处?
小结
知识点
- 静态链接把多个目标文件拼成可执行文件
- 步骤:合并段、分配地址、符号解析、重定位
- 静态库按需抽取用到的目标文件
- 好处是自包含,代价是体积大、更新麻烦
参考资料
- Wikipedia(zh):静态链接库:链接时并入可执行文件的库
- Wikipedia(zh):链接器:合并目标文件并解析符号
思考题答案(仅供参考)
思考题 1
大致包括:合并各个目标文件的同类段、为各段和符号分配最终地址、进行符号解析(把外部引用对应到定义)、以及完成重定位(填入真实地址)。
思考题 2
好处是自包含:可执行文件已包含所需的一切,运行时不必依赖外部库,部署简单、不怕缺库或被改。坏处是文件体积大、多个程序会重复携带同样的库代码造成内存浪费,而且库更新后需要重新链接每个使用它的程序。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪