# 第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["保存断点
(PC、PSW 压入内核栈)"] D --> E["保存通用寄存器
(保存进程现场)"] E --> F["识别中断源
(查询中断向量表)"] F --> G["跳转到中断服务程序
(PC ← 中断向量地址)"] G --> H["执行中断服务程序
(处理具体的中断事件)"] H --> I["恢复通用寄存器
(恢复进程现场)"] I --> J["恢复断点
(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["逻辑地址空间
0x0000 ~ 0xFFFF"] end subgraph MMU_Block["MMU(存储管理部件)"] TR1["地址变换函数 tr1()"] end subgraph PA_Phys["物理内存"] PA_M["区域 1
物理地址 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["逻辑地址空间
0x0000 ~ 0xFFFF"] end subgraph MMU_Block2["MMU(存储管理部件)"] TR2["地址变换函数 tr2()"] end subgraph PB_Phys["物理内存"] PB_M["区域 2
物理地址 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["触发保护异常 ✗
终止进程"] 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 -->|"中断/异常发生
(时钟中断、I/O中断、缺页等)"| C A -->|"系统调用
(int $0x80 / SWI)"| D C -->|"中断返回
(IRET)"| A D -->|"系统调用返回
(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["用户程序
printf(#quot;Hello#quot;)"] --> B["C 库函数
write(1, #quot;Hello#quot;, 5)"] B --> C["系统调用包装函数
将参数写入寄存器
EAX=4 (sys_write 号)
EBX=1 (文件描述符)
ECX=缓冲区地址
EDX=5 (长度)"] C --> D["软中断指令
int $0x80"] D --> E["CPU 模式切换
用户模式 → 内核模式
保存断点和现场"] E --> F["查询系统调用表
根据 EAX=4 找到
sys_write 函数地址"] F --> G["执行内核函数
sys_write()
实际完成屏幕输出"] G --> H["系统调用返回
恢复现场
内核模式 → 用户模式"] H --> I["返回用户程序
继续执行"] 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["外部中断
(硬件中断)"] A --> C["异常
(内部中断)"] B --> B1["I/O 中断
键盘、鼠标、网卡等设备发出"] B --> B2["时钟中断
RTC 周期性发出"] C --> C1["系统调用
用户执行 int $0x80 / SWI"] C --> C2["缺页异常
访问的页面不在内存中"] C --> C3["断点指令
调试器设置的断点"] C --> C4["算术溢出
除零错误等"] 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["进入内核
调度器决定是否切换进程"] B -->|"系统调用"| D["进入内核
执行内核函数"] B -->|"I/O 请求"| E["进程 P1 等待 I/O
CPU 分配给其他进程"] B -->|"进程结束"| F["进程 P1 终止
CPU 分配给其他进程"] C --> G{"调度器决策"} G -->|"继续执行 P1"| A G -->|"切换到 P2"| H["保存 P1 现场
恢复 P2 现场
执行进程 P2"] D --> I{"系统调用是否阻塞?"} I -->|"不阻塞"| A I -->|"需要等待"| E E --> J["P1 进入等待队列
CPU 执行进程 P2"] F --> K["回收 P1 资源
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["时钟中断
(RTC 硬件)"] MMU_HW["MMU 硬件
(地址转换)"] CPU_MODE["CPU 双模式
(IOPL/M[4:0])"] INT_HW["中断控制器
(PIC/APIC)"] end subgraph OS核心功能 PROC["进程管理
(调度、切换)"] MEM["内存管理
(地址隔离)"] PROT["系统保护
(内核安全)"] IO["I/O 管理
(设备驱动)"] 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章