CS-Notes/notes/计算机操作系统 - 链接.md
2020-11-17 00:32:18 +08:00

69 lines
2.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 计算机操作系统 - 链接
<!-- GFM-TOC -->
* [计算机操作系统 - 链接](#计算机操作系统---链接)
* [编译系统](#编译系统)
* [静态链接](#静态链接)
* [目标文件](#目标文件)
* [动态链接](#动态链接)
<!-- GFM-TOC -->
## 编译系统
以下是一个 hello.c 程序
```c
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
```
Unix 系统上由编译器把源文件转换为目标文件
```bash
gcc -o hello hello.c
```
这个过程大致如下
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b396d726-b75f-4a32-89a2-03a7b6e19f6f.jpg" width="800"/> </div><br>
- 预处理阶段处理以 # 开头的预处理命令
- 编译阶段翻译成汇编文件
- 汇编阶段将汇编文件翻译成可重定位目标文件
- 链接阶段将可重定位目标文件和 printf.o 等单独预编译好的目标文件进行合并得到最终的可执行目标文件
## 静态链接
静态链接器以一组可重定位目标文件为输入生成一个完全链接的可执行目标文件作为输出链接器主要完成以下两个任务
- 符号解析每个符号对应于一个函数一个全局变量或一个静态变量符号解析的目的是将每个符号引用与一个符号定义关联起来
- 重定位链接器通过把每个符号定义与一个内存位置关联起来然后修改所有对这些符号的引用使得它们指向这个内存位置
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/47d98583-8bb0-45cc-812d-47eefa0a4a40.jpg"/> </div><br>
## 目标文件
- 可执行目标文件可以直接在内存中执行
- 可重定位目标文件可与其它可重定位目标文件在链接阶段合并创建一个可执行目标文件
- 共享目标文件这是一种特殊的可重定位目标文件可以在运行时被动态加载进内存并链接
## 动态链接
静态库有以下两个问题
- 当静态库更新时那么整个程序都要重新进行链接
- 对于 printf 这种标准函数库如果每个程序都要有代码这会极大浪费资源
共享库是为了解决静态库的这两个问题而设计的 Linux 系统中通常用 .so 后缀来表示Windows 系统上它们被称为 DLL它具有以下特点
- 在给定的文件系统中一个库只有一个文件所有引用该库的可执行目标文件都共享这个文件它不会被复制到引用它的可执行文件中
- 在内存中一个共享库的 .text 已编译程序的机器代码的一个副本可以被不同的正在运行的进程共享
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/76dc7769-1aac-4888-9bea-064f1caa8e77.jpg"/> </div><br>