链接

编译

在unix系统中, 由编译器把源文件转换为目标文件:

1
gcc -o hello hello.c

过程如下:

compile

  • 预处理: 处理以#开头的预处理命令
  • 编译: 翻译成汇编文件
  • 汇编: 将汇编文件翻译成可重定向目标文件
  • 链接: 将可重定向目标文件和其他单独预编译好的目标文件合并, 最终得到可执行文件.

静态链接

静态链接器以一组可重定向目标文件为输入, 生成一个完全链接的可执行目标文件作为输出. 链接器主要完成两个任务:

  1. 符号解析: 每个符号对应一个函数, 一个全局变量, 或者一个静态变量, 符号解析的目的是将每个符号引用与一个符号定义关联起来.
  2. 重定位: 链接器通过把每个符号定义与一个内存位置关联起来, 然后修改所有对这些符号的引用, 使得他们指向这个内存位置.

static_link

目标文件

  • 可执行目标文件: 可以直接在内存中执行
  • 可重定向目标文件: 可与其他重定向目标文件在链接阶段合并, 创建一个可执行目标文件.
  • 共享目标文件: 是一种特殊的可重定向目标文件, 可以在运行时被动态加载进内存并链接.

动态链接

静态库存在下列两个问题:

  1. 当静态库更新时那么整个冲虚都需要重新进行链接
  2. 对于printf这种标准函数库, 如果每个程序都要有代码, 那么会极大的浪费资源.

共享库是为了解决静态库的这两个问题而设计的, 在Linux系统中用.so后缀表示, 在windows上被称为dll. 他具有以下特点:

  1. 在给定的文件系统中一个库只有一个文件, 所有引用该库的可执行目标都共享这个文件, 他不会被复制到引用他的可执行文件中.

  2. 在内存中, 一个共享库.text节(已编译程序的机器代码)的一个副本可以被不同的正在运行的进程共享.

dynamic_link