Files
obsidian/操作系统/01_系统运行机制/01_系统运行机制.md

697 lines
26 KiB
Markdown
Raw Permalink 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.
# 第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是由实时时钟RTCReal-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 操作后通过中断通知 CPUCPU 可以将等待该 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** | 低 3GB0x00000000 ~ 0xBFFFFFFF | 高 1GB0xC0000000 ~ 0xFFFFFFFF |
| **32 位 Windows** | 低 2GB0x00000000 ~ 0x7FFFFFFF | 高 2GB0x80000000 ~ 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 架构**:使用 CPSRCurrent 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章