Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

静态链接

复习

  • 重定位:把占位替换成真实地址
  • 目标文件格式:符号表与分段
  • 从源代码到可执行文件:链接这一步

TL;DR

  • 静态链接把多个目标文件拼成一个可执行文件
  • 它要合并各段、分配地址并完成重定位
  • 链接后的程序自包含,不依赖外部库文件
  • 代价是文件较大、库更新需要重新链接

正文

  有了目标文件和重定位,就可以把它们“拼”成可执行文件了。这一步叫链接(linking),而“在生成可执行文件时就把一切确定好”的做法,叫静态链接(static linking)。

链接器做的事

  链接器把多个目标文件(以及用到的库)合到一起,大致做这几件事:

  1. 合并同类段:把各个文件的代码段拼成一个大代码段,数据段同理
  2. 分配地址:给合并后的各段、各符号安排最终的内存位置
  3. 符号解析:把一个文件引用的外部名字,对应到另一个文件里提供的定义
  4. 重定位:把所有“待填地址”换成真实地址

  做完这些,就得到了一个完整的可执行文件。

静态库:按需抽取

  很多程序会用到标准库里的函数。一个静态库,其实就是一堆预先编译好的目标文件打包在一起。链接器链接时,会只把程序真正用到的那几个目标文件抽出来,接进可执行文件——不必把整个库都塞进去。

好处与代价

  静态链接的结果是自包含的:可执行文件里已经包含了它需要的一切,运行时不再依赖外部库文件。好处是:

  • 部署简单:拷过去就能跑,不怕缺库
  • 运行独立:不担心库被改坏或版本不对

  代价则是:

  • 文件大:每个程序都自带一份库代码,重复占空间
  • 内存浪费:多个程序运行时,各自带着同样的库副本
  • 更新麻烦:库修了 bug,得把每个用它重新链接过的程序都重新链接

  正是这些代价,催生了另一种思路:别在编译时就把库链进去,等运行时再说。 这就是下一章的动态链接。

思考题 1

  静态链接大致要做哪几件事?

思考题 2

  静态链接的程序“自包含”,有什么好处和坏处?

小结

知识点

  • 静态链接把多个目标文件拼成可执行文件
  • 步骤:合并段、分配地址、符号解析、重定位
  • 静态库按需抽取用到的目标文件
  • 好处是自包含,代价是体积大、更新麻烦

参考资料

  1. Wikipedia(zh):静态链接库:链接时并入可执行文件的库
  2. Wikipedia(zh):链接器:合并目标文件并解析符号

思考题答案(仅供参考)

思考题 1

  大致包括:合并各个目标文件的同类段、为各段和符号分配最终地址、进行符号解析(把外部引用对应到定义)、以及完成重定位(填入真实地址)。

思考题 2

  好处是自包含:可执行文件已包含所需的一切,运行时不必依赖外部库,部署简单、不怕缺库或被改。坏处是文件体积大、多个程序会重复携带同样的库代码造成内存浪费,而且库更新后需要重新链接每个使用它的程序。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪