# 第1.5章 系统运行机制

> [!abstract] 学习目标
> 1. 理解多进程并发运行的场景及其对硬件支持的需求
> 2. 掌握中断机制的工作原理，理解时钟中断对操作系统的核心作用
> 3. 理解 MMU（存储管理部件）如何实现进程隔离与地址转换
> 4. 掌握 CPU 双模式工作原理（内核模式 vs 用户模式）及特权指令的划分
> 5. 理解系统调用的完整流程（从用户程序到内核服务）
> 6. 理解广义中断的分类（外部中断、异常）
> 7. 能够综合运用上述机制，解释操作系统如何实现多任务并发执行

> [!info] 前置知识
> - 计算机组成原理：CPU、内存、寄存器的基本概念
> - 二进制与地址的基本概念
> - 进程的基本概念（参见 [[06_进程控制]]）

---

## 一、为什么需要系统运行机制？

### 1.1 多进程并发运行场景

在现代操作系统中，多个进程需要**并发**（交替）执行。考虑两个进程 A 和 B：

```
进程 A 的代码：          进程 B 的代码：
A:1                      B:1
A:2                      B:2
A:3                      B:3
A:4                      B:4
A:5                      B:5
```

实际在 CPU 上的执行顺序可能是：

```
时间线 →  A:1  B:1  A:2  B:2  A:3  B:3  B:4  A:4  A:5  B:5
```

> [!question] 核心问题
> 这种交替执行不会自然发生！CPU 只是一个顺序执行指令的"傻瓜机器"，它不会自动在 A 和 B 之间切换。要实现多进程并发运行，**必须有硬件和操作系统的支持**。

实现多进程并发运行需要以下关键机制：

| 机制 | 作用 |
|------|------|
| [[#二、中断机制]] | 让 CPU 能够响应外部事件，实现进程切换的"触发器" |
| [[#三、MMU 存储管理部件]] | 实现进程间的地址隔离，防止互相干扰 |
| [[#四、CPU 工作模式]] | 区分特权操作，保护操作系统内核不被用户程序破坏 |
| [[#五、系统调用机制]] | 为用户程序提供受控的内核服务访问途径 |

---

## 二、中断机制

### 2.1 什么是中断？

**中断**（Interrupt）是指 CPU 在执行程序的过程中，收到来自外部设备或内部异常的信号，暂停当前程序的执行，转而去处理该事件，处理完毕后再返回原程序继续执行的过程。

> [!tip] 生活类比
> 中断就像你在看书时手机响了（外部中断），你先记住看到哪一页（保存断点），然后去接电话（处理中断），接完电话后回到那一页继续看（恢复执行）。

### 2.2 中断处理流程

CPU 处理一次中断的完整流程如下：

```mermaid
flowchart TD
    A["CPU 正在执行用户程序"] --> B{"收到中断请求？"}
    B -- "否" --> A
    B -- "是" --> C["关中断（防止嵌套中断）"]
    C --> D["保存断点<br>（PC、PSW 压入内核栈）"]
    D --> E["保存通用寄存器<br>（保存进程现场）"]
    E --> F["识别中断源<br>（查询中断向量表）"]
    F --> G["跳转到中断服务程序<br>（PC ← 中断向量地址）"]
    G --> H["执行中断服务程序<br>（处理具体的中断事件）"]
    H --> I["恢复通用寄存器<br>（恢复进程现场）"]
    I --> J["恢复断点<br>（PC、PSW 出栈）"]
    J --> K["开中断"]
    K --> L["继续执行用户程序"]

    style A fill:#e1f5fe
    style C fill:#ffcdd2
    style D fill:#ffcdd2
    style G fill:#fff3e0
    style H fill:#fff3e0
    style J fill:#e1f5fe
```

**关键步骤详解**：

1. **关中断**：CPU 响应中断后立即关闭中断信号接收，防止在处理一个中断时又被另一个中断打断（中断嵌套）
2. **保存断点**：将程序计数器（PC）和程序状态字（PSW）压入内核栈，记录"回来后从哪里继续执行"
3. **保存现场**：将通用寄存器的内容保存到进程的 PCB（进程控制块）中
4. **识别中断源**：通过中断向量表（Interrupt Vector Table）确定是哪个设备发出的中断
5. **执行中断服务程序**：跳转到对应的中断处理函数，完成实际的处理工作
6. **恢复现场和断点**：从 PCB 恢复寄存器，从栈中弹出 PC 和 PSW
7. **开中断**：重新允许 CPU 接收中断信号

### 2.3 时钟中断 — 操作系统的"心跳"

> [!important] 时钟中断的核心地位
> **时钟中断**（Timer Interrupt）是由实时时钟（RTC，Real-Time Clock）硬件周期性产生的中断，是操作系统实现进程管理的最关键机制。

时钟中断的工作原理：

```mermaid
sequenceDiagram
    participant RTC as 实时时钟 (RTC)
    participant CPU
    participant OS as 操作系统
    participant PA as 进程 A
    participant PB as 进程 B

    PA->>CPU: 正在执行进程 A
    RTC->>CPU: 时钟中断（每 10ms）
    CPU->>OS: 保存 A 的现场，进入内核
    OS->>OS: 检查：A 的时间片用完了吗？
    OS->>CPU: 切换到进程 B
    CPU->>PB: 恢复 B 的现场，执行进程 B
    RTC->>CPU: 时钟中断（每 10ms）
    CPU->>OS: 保存 B 的现场，进入内核
    OS->>CPU: 切换到进程 A
    CPU->>PA: 恢复 A 的现场，执行进程 A
```

**时钟中断频率**：通常为 **10ms 一次**（即每秒 100 次），也称为 **时钟滴答**（Clock Tick）。

> [!warning] 没有时钟中断会怎样？
> 如果没有时钟中断，CPU 一旦开始执行某个进程，就永远不会主动让出 CPU。操作系统将无法实现"分时"，也就无法让多个进程看起来在"同时"运行。时钟中断是操作系统实现**抢占式调度**的基础。

### 2.4 中断对操作系统的意义

中断机制对操作系统具有根本性的意义：

1. **实现进程并发执行**：时钟中断迫使 CPU 周期性地将控制权交还给操作系统，操作系统可以决定切换到哪个进程
2. **实现 I/O 管理**：设备完成 I/O 操作后通过中断通知 CPU，CPU 可以将等待该 I/O 的进程唤醒
3. **实现系统调用**：用户程序通过软中断指令（如 `int $0x80`）请求内核服务
4. **异常处理**：CPU 内部发生的异常（如除零、缺页）通过中断机制通知操作系统处理

---

## 三、MMU（存储管理部件）

### 3.1 为什么需要 MMU？

> [!question] 核心问题
> 如果没有地址隔离，进程 A 可以直接读写进程 B 的内存空间，甚至可以修改操作系统内核的代码！这是绝对不允许的。

**没有 MMU 时**：程序中使用的地址 = 物理地址

```
进程 A:  MOV [0x1000], 1    → 直接写物理地址 0x1000
进程 B:  MOV [0x1000], 2    → 也写物理地址 0x1000 ！冲突！
```

**有 MMU 时**：程序中使用的地址是**逻辑地址**（虚拟地址），经过 MMU 转换后才是**物理地址**

```
进程 A:  MOV [0x1000], 1    → MMU 转换 → 物理地址 0x5000
进程 B:  MOV [0x1000], 2    → MMU 转换 → 物理地址 0x8000  ✓ 不冲突
```

### 3.2 MMU 地址转换原理

MMU 通过**地址变换函数**将不同进程的逻辑地址映射到不同的物理地址区域：

```mermaid
flowchart LR
    subgraph 进程A["进程 A"]
        LA["逻辑地址空间<br>0x0000 ~ 0xFFFF"]
    end

    subgraph MMU_Block["MMU（存储管理部件）"]
        TR1["地址变换函数 tr1()"]
    end

    subgraph PA_Phys["物理内存"]
        PA_M["区域 1<br>物理地址 0x5000 ~ 0x14FFF"]
    end

    LA -->|"逻辑地址 0x1000"| TR1
    TR1 -->|"物理地址 0x6000"| PA_M

    style LA fill:#e1f5fe
    style TR1 fill:#fff3e0
    style PA_M fill:#e8f5e9
```

```mermaid
flowchart LR
    subgraph 进程B["进程 B"]
        LB["逻辑地址空间<br>0x0000 ~ 0xFFFF"]
    end

    subgraph MMU_Block2["MMU（存储管理部件）"]
        TR2["地址变换函数 tr2()"]
    end

    subgraph PB_Phys["物理内存"]
        PB_M["区域 2<br>物理地址 0x8000 ~ 0x17FFF"]
    end

    LB -->|"逻辑地址 0x1000"| TR2
    TR2 -->|"物理地址 0x9000"| PB_M

    style LB fill:#e1f5fe
    style TR2 fill:#fff3e0
    style PB_M fill:#e8f5e9
```

**关键概念**：

| 术语 | 含义 |
|------|------|
| **逻辑地址**（虚拟地址） | 程序中使用的地址，每个进程从 0 开始编址 |
| **物理地址** | 实际内存硬件上的地址，全局唯一 |
| **地址变换函数** | MMU 中的映射规则，每个进程有独立的变换函数 |

> [!tip] 进程隔离的本质
> 每个进程都有自己独立的**逻辑地址空间**，通过 MMU 映射到物理内存中互不重叠的区域。进程 A 无法访问进程 B 的物理内存区域，从而实现了**进程隔离**。

### 3.3 页表与 MMU 保护机制

在现代操作系统中，MMU 通常通过**页表**（Page Table）实现地址转换。页表中除了地址映射信息外，还包含保护位：

**页表项中的 U/S 位**：

| U/S 位值 | 含义 | 访问权限 |
|----------|------|----------|
| 0 | Supervisor（内核页） | 仅内核模式可访问 |
| 1 | User（用户页） | 内核模式和用户模式均可访问 |

**CPU 标志寄存器中的 IOPL 位**：

- `IOPL = 0` 或 `1`：用户模式（受限）
- `IOPL = 3`：内核模式（拥有全部 I/O 权限）

**保护机制的工作方式**：

```mermaid
flowchart TD
    A["CPU 执行指令，访问逻辑地址"] --> B["MMU 查页表"]
    B --> C{"当前 CPU 模式？"}
    C -- "用户模式" --> D{"页表 U/S 位？"}
    D -- "U/S = 1（用户页）" --> E["允许访问 ✓"]
    D -- "U/S = 0（内核页）" --> F["触发保护异常 ✗<br>终止进程"]
    C -- "内核模式" --> G["允许访问所有页面 ✓"]

    style E fill:#c8e6c9
    style F fill:#ffcdd2
    style G fill:#c8e6c9
```

### 3.4 Linux 地址空间划分

操作系统将每个进程的逻辑地址空间划分为**用户空间**和**内核空间**：

| 操作系统 | 用户空间 | 内核空间 |
|----------|----------|----------|
| **32 位 Linux** | 低 3GB（0x00000000 ~ 0xBFFFFFFF） | 高 1GB（0xC0000000 ~ 0xFFFFFFFF） |
| **32 位 Windows** | 低 2GB（0x00000000 ~ 0x7FFFFFFF） | 高 2GB（0x80000000 ~ 0xFFFFFFFF） |

> [!info] 为什么内核空间在高地址？
> 将内核空间放在高地址是一种约定。在 Linux 中，所有进程共享同一个内核空间映射（内核只有一份），但每个进程的用户空间是独立的。当 CPU 处于用户模式时，访问内核空间会触发保护异常。

> [!tip] 相关链接
> 关于存储管理的更多内容，参见 [[13_存储管理基础]] 和 [[14_分页存储管理]]。

---

## 四、CPU 工作模式

### 4.1 双模式设计

现代 CPU 设计了两种工作模式，用于区分"谁可以执行什么指令"：

| 模式 | 别名 | 权限 | 使用者 |
|------|------|------|--------|
| **内核模式** | 系统态、核心态、管态 | 可执行所有指令，访问所有内存 | 操作系统内核 |
| **用户模式** | 用户态、目态 | 只能执行非特权指令，不能访问内核空间 | 用户程序 |

> [!warning] 为什么需要两种模式？
> 如果所有程序都运行在内核模式，任何一个用户程序都可以：修改操作系统代码、直接操作硬件、访问其他进程的内存。这将导致系统完全不安全。双模式设计是操作系统**自我保护**的基础。

### 4.2 特权指令 vs 非特权指令

| 分类 | 特点 | 示例 |
|------|------|------|
| **特权指令** | 只能在内核模式下执行 | I/O 指令、停机指令（HLT）、特殊寄存器访问（如修改页表基址寄存器） |
| **非特权指令** | 在任何模式下均可执行 | 算术逻辑运算（ADD、SUB）、寄存器操作（MOV）、内存访问（普通读写） |

> [!warning] 用户模式执行特权指令会怎样？
> 如果 CPU 处于用户模式时执行了特权指令，CPU 会立即触发一个**保护异常**（Protection Exception），操作系统会终止该进程（通常表现为 "Segmentation Fault"）。

### 4.3 不同架构的模式标识

CPU 通过标志寄存器中的特定位来标识当前工作模式：

**x86 架构**：使用 FLAGS 寄存器中的 **IOPL**（I/O Privilege Level）字段

```
FLAGS 寄存器:
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ ... │ IOPL│ IOPL│ ... │ IF  │ ... │ ZF  │ CF  │
│     │ (13)│ (12)│     │ (9) │     │ (6) │ (0) │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
        ├───IOPL───┤
        00 = Ring 0（内核模式）
        11 = Ring 3（用户模式）
```

**ARM 架构**：使用 CPSR（Current Program Status Register）中的 **M[4:0]** 位

```
CPSR 寄存器:
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ ... │ M4  │ M3  │ M2  │ M1  │ M0  │ ... │     │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
        ├─── M[4:0] ───┤
        10000 = User（用户模式）
        10011 = Supervisor（内核模式）
        10111 = Abort
        11011 = Undefined
        10010 = IRQ
        10001 = FIQ
```

### 4.4 CPU 模式切换

CPU 模式切换发生在以下场景：

```mermaid
flowchart TD
    subgraph 用户模式区["用户模式（User Mode）"]
        A["执行用户程序"]
        B["执行非特权指令"]
    end

    subgraph 内核模式区["内核模式（Kernel Mode）"]
        C["处理中断/异常"]
        D["执行系统调用"]
        E["执行特权指令"]
    end

    A -->|"中断/异常发生<br>（时钟中断、I/O中断、缺页等）"| C
    A -->|"系统调用<br>（int $0x80 / SWI）"| D
    C -->|"中断返回<br>（IRET）"| A
    D -->|"系统调用返回<br>（IRET）"| A
    E -->|"设置 IOPL/M[4:0]"| A

    style A fill:#e1f5fe
    style B fill:#e1f5fe
    style C fill:#fff3e0
    style D fill:#fff3e0
    style E fill:#fff3e0
```

**用户模式 → 内核模式**（两种途径）：

1. **中断/异常**：硬件自动切换
   - 时钟中断、I/O 中断
   - 缺页异常、除零异常
   - 系统调用（软中断）

2. **系统调用**：用户程序主动发起
   - x86：执行 `int $0x80` 指令
   - ARM：执行 `SWI` 指令

**内核模式 → 用户模式**：

- 执行中断返回指令（x86: `IRET`），恢复用户模式的状态

---

## 五、系统调用机制

### 5.1 什么是系统调用？

**系统调用**（System Call）是操作系统提供给用户程序的**唯一合法途径**，用于请求内核提供的服务。

> [!tip] 生活类比
> 系统调用就像银行柜台：你（用户程序）不能自己进入金库（内核空间）取钱，但你可以通过柜台窗口（系统调用接口）告诉工作人员（内核）你要做什么，工作人员帮你完成后再把结果交给你。

### 5.2 系统调用的必要性

用户程序**不能直接调用**内核函数，原因：

1. **地址隔离**：内核函数位于内核空间，用户模式无法访问
2. **权限保护**：内核函数可能执行特权操作（如 I/O），用户模式无权执行
3. **安全控制**：内核需要验证参数的合法性，防止恶意调用

### 5.3 系统调用的完整流程

以 `printf("Hello")` 为例，完整调用链如下：

```mermaid
flowchart TD
    A["用户程序<br>printf(#quot;Hello#quot;)"] --> B["C 库函数<br>write(1, #quot;Hello#quot;, 5)"]
    B --> C["系统调用包装函数<br>将参数写入寄存器<br>EAX=4 (sys_write 号)<br>EBX=1 (文件描述符)<br>ECX=缓冲区地址<br>EDX=5 (长度)"]
    C --> D["软中断指令<br>int $0x80"]
    D --> E["CPU 模式切换<br>用户模式 → 内核模式<br>保存断点和现场"]
    E --> F["查询系统调用表<br>根据 EAX=4 找到<br>sys_write 函数地址"]
    F --> G["执行内核函数<br>sys_write()<br>实际完成屏幕输出"]
    G --> H["系统调用返回<br>恢复现场<br>内核模式 → 用户模式"]
    H --> I["返回用户程序<br>继续执行"]

    style A fill:#e1f5fe
    style B fill:#e1f5fe
    style C fill:#e1f5fe
    style D fill:#ffcdd2
    style E fill:#fff3e0
    style F fill:#fff3e0
    style G fill:#fff3e0
    style H fill:#ffcdd2
    style I fill:#e1f5fe
```

### 5.4 系统调用的参数传递方式

用户程序通过**寄存器**将参数传递给内核：

**x86 架构的系统调用参数寄存器**：

| 寄存器 | 用途 |
|--------|------|
| **EAX** | 系统调用号（标识调用哪个内核函数） |
| **EBX** | 第 1 个参数 |
| **ECX** | 第 2 个参数 |
| **EDX** | 第 3 个参数 |
| **ESI** | 第 4 个参数 |
| **EDI** | 第 5 个参数 |
| **EBP** | 第 6 个参数 |

> [!info] `int $0x80` 指令的作用
> `int $0x80` 是 x86 的**软中断指令**（Software Interrupt）。执行该指令时，CPU 会：
> 1. 自动将 FLAGS、CS、IP 压入内核栈（保存断点）
> 2. 将 CPU 模式切换为内核模式
> 3. 从中断向量表的第 0x80 号表项取出中断服务程序入口地址
> 4. 跳转到该地址开始执行（即系统调用处理函数 `system_call`）

### 5.5 系统调用的底层实现

```asm
; x86 Linux 系统调用的底层实现示意

; 用户程序部分（C 库包装）
mov eax, 4          ; 系统调用号 = 4 (sys_write)
mov ebx, 1          ; 文件描述符 = 1 (stdout)
mov ecx, msg        ; 缓冲区地址
mov edx, 5          ; 字节数
int 0x80            ; 触发软中断，进入内核

; 内核部分（system_call）
system_call:
    ; 1. 保存所有寄存器到内核栈
    push eax
    push ebx
    push ecx
    push edx
    ; ...

    ; 2. 根据 EAX 的值查系统调用表
    call [sys_call_table + eax*4]

    ; 3. 返回值放在 EAX 中
    mov [esp + 恢复位置], eax

    ; 4. 恢复寄存器，返回用户模式
    pop edx
    pop ecx
    pop ebx
    pop eax
    iret
```

### 5.6 常见的系统调用

| 系统调用号 | 函数名 | 功能 |
|-----------|--------|------|
| 1 | `sys_exit` | 终止进程 |
| 2 | `sys_fork` | 创建子进程 |
| 3 | `sys_read` | 读文件 |
| 4 | `sys_write` | 写文件 |
| 5 | `sys_open` | 打开文件 |
| 6 | `sys_close` | 关闭文件 |

---

## 六、异常（广义中断）

### 6.1 广义中断的分类

在操作系统中，**广义的中断**包括两大类：

```mermaid
flowchart TD
    A["广义中断"] --> B["外部中断<br>（硬件中断）"]
    A --> C["异常<br>（内部中断）"]

    B --> B1["I/O 中断<br>键盘、鼠标、网卡等设备发出"]
    B --> B2["时钟中断<br>RTC 周期性发出"]

    C --> C1["系统调用<br>用户执行 int $0x80 / SWI"]
    C --> C2["缺页异常<br>访问的页面不在内存中"]
    C --> C3["断点指令<br>调试器设置的断点"]
    C --> C4["算术溢出<br>除零错误等"]

    style A fill:#fff3e0
    style B fill:#e1f5fe
    style C fill:#ffcdd2
```

### 6.2 外部中断 vs 异常

| 特征 | 外部中断 | 异常 |
|------|----------|------|
| **来源** | CPU 外部设备 | CPU 内部执行指令时产生 |
| **发生时机** | 与当前指令无关，随机发生 | 与当前指令直接相关 |
| **是否可屏蔽** | 可屏蔽中断（INTR）可被 IF 位屏蔽 | 不可屏蔽 |
| **典型例子** | I/O 中断、时钟中断 | 缺页、除零、系统调用 |

### 6.3 常见异常类型

| 异常类型 | 触发条件 | 处理方式 |
|----------|----------|----------|
| **系统调用** | 执行 `int $0x80` 或 `SWI` | 查系统调用表，执行对应内核函数 |
| **缺页异常** | 访问的虚拟页面不在物理内存中 | 从磁盘调入页面（参见 [[14_分页存储管理]]） |
| **断点指令** | 调试器在代码中设置断点 | 暂停程序，将控制权交给调试器 |
| **算术溢出** | 除零、溢出等运算错误 | 终止进程或通知进程处理 |
| **保护异常** | 用户模式执行特权指令或访问内核空间 | 终止进程（Segmentation Fault） |

---

## 七、多任务并发执行的综合场景

### 7.1 操作系统如何实现多任务并发

操作系统通过**中断驱动**的方式实现多任务并发执行。以下是几种典型的触发场景：

```mermaid
flowchart TD
    A["CPU 正在执行进程 P1"] --> B{"发生了什么？"}

    B -->|"时钟中断（每 10ms）"| C["进入内核<br>调度器决定是否切换进程"]
    B -->|"系统调用"| D["进入内核<br>执行内核函数"]
    B -->|"I/O 请求"| E["进程 P1 等待 I/O<br>CPU 分配给其他进程"]
    B -->|"进程结束"| F["进程 P1 终止<br>CPU 分配给其他进程"]

    C --> G{"调度器决策"}
    G -->|"继续执行 P1"| A
    G -->|"切换到 P2"| H["保存 P1 现场<br>恢复 P2 现场<br>执行进程 P2"]

    D --> I{"系统调用是否阻塞？"}
    I -->|"不阻塞"| A
    I -->|"需要等待"| E

    E --> J["P1 进入等待队列<br>CPU 执行进程 P2"]
    F --> K["回收 P1 资源<br>CPU 执行就绪队列中的进程"]

    style A fill:#e1f5fe
    style C fill:#fff3e0
    style D fill:#fff3e0
    style E fill:#ffcdd2
    style F fill:#ffcdd2
```

### 7.2 四种典型场景详解

**场景一：时钟中断触发进程切换**

```
时间线：
  P1 执行 → [时钟中断] → OS 调度 → P2 执行 → [时钟中断] → OS 调度 → P1 执行
            ↑ 10ms                 ↑ 10ms
```

**场景二：系统调用触发内核执行**

```
P1 执行 printf → [int $0x80] → 内核执行 sys_write → [iret] → P1 继续执行
```

**场景三：I/O 等待导致 CPU 重分配**

```
P1 请求读磁盘 → P1 进入等待队列 → CPU 执行 P2 → 磁盘中断 → P1 就绪 → P1 继续执行
```

**场景四：进程结束释放 CPU**

```
P1 执行 exit() → P1 终止 → OS 回收资源 → CPU 执行就绪队列中的 P2
```

> [!important] 中断是操作系统的"发动机"
> 可以说，**没有中断就没有操作系统**。中断机制是操作系统实现进程管理、I/O 管理、内存管理等所有核心功能的基础。时钟中断让 OS 能够"定期检查"系统状态，I/O 中断让 OS 能够响应设备事件，系统调用让 OS 能够为用户程序提供服务。

---

## 八、机制之间的关系

理解了各个机制后，需要看到它们之间的协同关系：

```mermaid
flowchart TD
    subgraph 硬件支持
        CLK["时钟中断<br>（RTC 硬件）"]
        MMU_HW["MMU 硬件<br>（地址转换）"]
        CPU_MODE["CPU 双模式<br>（IOPL/M[4:0]）"]
        INT_HW["中断控制器<br>（PIC/APIC）"]
    end

    subgraph OS核心功能
        PROC["进程管理<br>（调度、切换）"]
        MEM["内存管理<br>（地址隔离）"]
        PROT["系统保护<br>（内核安全）"]
        IO["I/O 管理<br>（设备驱动）"]
    end

    CLK -->|"触发进程切换"| PROC
    MMU_HW -->|"地址转换 + 保护"| MEM
    CPU_MODE -->|"特权级隔离"| PROT
    INT_HW -->|"设备事件通知"| IO

    PROC -->|"选择下一个进程"| MEM
    MEM -->|"提供地址空间"| PROC
    PROT -->|"限制用户操作"| PROC

    style CLK fill:#ffcdd2
    style MMU_HW fill:#ffcdd2
    style CPU_MODE fill:#ffcdd2
    style INT_HW fill:#ffcdd2
    style PROC fill:#e1f5fe
    style MEM fill:#e1f5fe
    style PROT fill:#e1f5fe
    style IO fill:#e1f5fe
```

> [!tip] 核心要点
> 操作系统的四大运行机制（中断、MMU、CPU 模式、系统调用）不是孤立的，而是相互配合：
> - **中断**提供了"进入内核"的途径
> - **CPU 模式**确保了"谁能做什么"
> - **MMU** 保证了"谁的内存谁用"
> - **系统调用**提供了"受控的内核访问"

---

## 思考与练习

以下是 PPT 中给出的复习思考题：

1. **什么是逻辑地址、物理地址？什么是内核空间、用户空间？**
   - 提示：逻辑地址是程序中使用的地址，物理地址是内存硬件的实际地址；内核空间是操作系统运行的区域，用户空间是应用程序运行的区域

2. **MMU 的功能是什么，如何实现进程隔离？**
   - 提示：MMU 负责逻辑地址到物理地址的转换；每个进程有独立的地址变换函数，映射到不同的物理区域

3. **特权指令与非特权指令的特点？**
   - 提示：特权指令只能在内核模式执行（如 I/O 指令、停机指令），非特权指令在任何模式都可执行（如算术运算）

4. **两种 CPU 工作模式的特点？**
   - 提示：内核模式可执行所有指令、访问所有内存；用户模式只能执行非特权指令、不能访问内核空间

5. **如何利用 MMU 与工作模式防止用户程序破坏 OS？**
   - 提示：MMU 通过页表 U/S 位将内核页标记为仅内核模式可访问；CPU 在用户模式执行特权指令会触发保护异常

6. **CPU 模式切换方法？**
   - 提示：用户→内核：中断/异常/系统调用（硬件自动切换）；内核→用户：执行 IRET 指令

7. **系统调用的作用、原理和实现过程？**
   - 提示：作用是让安全地访问内核服务；原理是通过软中断指令触发模式切换；实现过程是参数通过寄存器传递，查系统调用表找到对应函数执行

8. **时钟中断对操作系统的作用？**
   - 提示：时钟中断是操作系统实现进程并发执行的基础，它迫使 CPU 周期性地将控制权交还给 OS，使 OS 能够进行进程调度

9. **中断对操作系统的意义？**
   - 提示：中断是操作系统的"发动机"，是实现进程管理、I/O 管理、系统调用等所有核心功能的基础

---

## 相关笔记

- [[02_Linux基础]] — Linux 系统的基本使用
- [[06_进程控制]] — 进程的创建、终止与管理
- [[11_处理机调度]] — 进程调度算法（时钟中断的实际应用）
- [[13_存储管理基础]] — 存储管理的基本概念
- [[14_分页存储管理]] — 分页存储与 MMU 的详细实现

---

## 参考资料

- 《操作系统概念》（Operating System Concepts）第1章、第2章
- 《深入理解计算机系统》（CSAPP）第1章、第9章
- 《现代操作系统》（Modern Operating Systems）第2章
