CS-Notes全部笔记在阅读器中打开

计算机操作系统 - 链接

本文目录

编译系统

以下是一个 hello.c 程序:

#include <stdio.h>

int main()
{
    printf("hello, world\n");
    return 0;
}

在 Unix 系统上,由编译器驱动程序 gcc 把源文件转换为可执行目标文件。

gcc -o hello hello.c

这个过程大致如下:

编译系统的配图

静态链接

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

例如 main.c 调用了 sum.c 中定义的 sum(见下图)。单独编译 main.c 时不知道 sum 在哪里,main.o 中调用指令的目标位移先填 0,并记下一条重定位条目“这里要指向 sum”。链接时先在 sum.o 中找到 sum 的定义(符号解析),再把两个文件的代码合并、确定 sum 的地址,按重定位条目算出调用指令到 sum 的相对位移并填回(重定位)。

静态链接的配图

目标文件

动态链接

静态库(Linux 上是 .a 文件)是多个可重定位目标文件的打包,静态链接时把用到的目标文件复制进可执行文件。它有以下两个问题:

共享库是为了解决静态库的这两个问题而设计的,在 Linux 系统中通常用 .so 后缀来表示,Windows 系统上它们被称为 DLL。它具有以下特点:

代价是程序运行时依赖系统中有版本兼容的共享库,缺少时程序无法启动;程序启动时还要由动态链接器加载共享库并完成重定位,比静态链接的程序多一些启动开销。

动态链接的配图

参考资料

在阅读器中可以用目录和搜索、切换深色模式、练习这篇笔记中的面试题:打开《计算机操作系统 - 链接》