

## 程序、进程与线程

### 程序

#### 定义

程序是存储在硬盘的一组指令集和，它是对计算任务的完整描述，是一个被动实体。类似于一本菜谱，记录了完整的烹饪步骤。

#### 核心特征

| 属性           | 说明                                                      |
| :------------- | :-------------------------------------------------------- |
| **静态性**     | 程序是一个文件（如 .exe、.go），不占用 CPU 或内存执行资源 |
| **持久性**     | 可长期存在于存储介质上                                    |
| **无生命周期** | 没有创建、运行、消亡的状态变迁                            |

### 进程

#### 定义

进程是程序的一次动态执行过程，是操作系统进行资源分配的基本单位。它就像按照菜谱进行烹饪的过程，需要占用资源，有始有终。它由以下三部分构成。

| 组成部分              | 作用                                                   |
| :-------------------- | :----------------------------------------------------- |
| **程序段**            | 描述进程要完成的功能，是控制进程执行的指令集           |
| **数据段**            | 程序执行时所需的数据和工作区（全局变量、堆等）         |
| **进程控制块（PCB）** | 包含进程的描述信息和控制信息，是**进程存在的唯一标志** |

#### 核心特征

- **动态性**：进程有生命周期（创建 → 就绪 → 运行 → 阻塞 → 终止）
- **独立性**：每个进程拥有独立的地址空间（虚拟内存空间、代码、数据、系统资源的集合）
- **并发性**：多个进程可在宏观上同时运行
- **资源拥有者**：进程拥有独立的文件描述符、环境变量、用户ID等资源

### 线程

#### 定义

线程是CPU进行运算调度的最小单位，是进程中的一条执行路径，一个进程至少有一个线程（也就是主线程）。它就像多位厨师共用厨房的资源（水、灶台、食材等），但是每人也都有自己的独有的刀具、围裙等，他们需要协调使用厨房做菜。

#### 核心特征

线程虽然共享进程的资源，但每个线程拥有自己的**私有数据**：

| **独有内容**        | **说明**                           |
| :------------------ | :--------------------------------- |
| 线程 ID             | 唯一标识                           |
| 寄存器状态          | 包括程序计数器（PC）和栈指针       |
| 栈                  | 独立运行栈，用于函数调用和局部变量 |
| 信号掩码            | 线程级别的信号处理设置             |
| 优先级              | 调度优先级                         |
| 线程专用存储（TLS） | 线程私有的全局变量                 |



## 用户态与内核态

### 内核态

运行操作系统内核代码，拥有对硬件的完全控制权，负责管理内存、进程、文件系统、网络等底层资源。

### 用户态

运行用户应用程序，无法直接访问硬件或内核数据结构，必须通过 系统调用（System Call）请求内核代为执行特权操作。

### 切换过程

为了保护系统安全与稳定，操作系统会对CPU的执行权限进行分级，不同的CPU架构有不同的等级，但是通常都遵循应用在最低特权级（用户态）运行，内核在次高特权级（内核态）运行，通过CPU硬件强制隔离特权操作。当在X86架构的CPU运行时，一个应用程序需要执行特权操作（比如读写文件），过程大致是这样的：

1. **触发**
    程序调用 `read()` 等库函数，最终执行 CPU 的 `syscall` 指令。这条指令告诉 CPU：“我要切换到内核态干正事”。
2. **CPU 硬件自动切换**
    CPU 在硬件层面做三件关键事：
   - 把特权级从 **Ring 3（用户态）** 切换为 **Ring 0（内核态）**。
   - 将栈指针从用户栈切换到**内核栈**（从 MSR 中读取预设的内核栈指针）。
   - 把返回地址（下一条指令）和标志寄存器保存到特定寄存器（如 `rcx`、`r11`），然后跳转到内核预先设置好的**入口函数**。
3. **内核软处理**
    入口函数将刚才没来得及保存的全部寄存器压入内核栈（形成 `pt_regs` 结构），然后根据**系统调用号**（放在 `rax` 通用寄存器中）从系统调用表里找到对应的内核函数（如 `ksys_read`）并执行。
4. **内核执行 & 返回**
    内核函数完成实际工作（检查权限、读取数据等），把结果放在 `rax` 通用寄存器中。返回前，内核检查是否有其他任务需要处理（如信号、调度），然后通过 `sysret` 指令恢复之前保存的寄存器、用户栈和返回地址，特权级自动切回 **Ring 3**，程序从当初的下一条指令继续运行。

