用户态 v.s 内核态
核心概念与特权级
本质
用户态/内核态本质上是 CPU 的运行权限级别,是硬件提供的机制。 操作系统是这套机制的”使用者”和”管理者”。
- 内核态(Ring 0):可执行一切指令,访问所有硬件资源
- 用户态(Ring 3):受限,只能执行普通指令,无法直接操作硬件或访问内核数据结构
判断一个程序运行在什么态的唯一标准:其有无执行特权指令的能力。


两种模式对比
| 内核态(Kernel Mode) | 用户态(User Mode) | |
|---|---|---|
| CPU 特权级 | Ring 0(最高权限) | Ring 3(最低权限) |
| 执行指令 | 所有指令(含特权指令) | 只能执行非特权指令 |
| 访问资源 | 全部硬件、全部内存 | 只能访问自己的地址空间 |
| 运行内容 | OS 内核、设备驱动、中断处理 | 普通应用程序 |
| 崩溃后果 | 系统崩溃(蓝屏/kernel panic) | 仅该程序崩溃 |
| 内存空间 | 内核空间(共享) | 用户空间(隔离) |
特权指令
只能在内核态执行的指令,包括:
- 硬件控制:设置中断使能、修改处理器状态寄存器
- 内存管理:修改页表、设置内存保护
- 进程管理:创建/终止进程、更改进程优先级
- I/O 操作:直接访问硬件设备或端口
中断屏蔽字寄存器属于 I/O 接口中的 I/O 端口,设置它属于 I/O 指令 → 特权指令。
状态切换与系统调用
状态切换的时机
用户态 → 内核态只能通过以下三种方式:
| 方式 | 触发类型 | 举例 |
|---|---|---|
| 系统调用 | 主动 | 用户程序请求 OS 服务(如 read、fork) |
| 异常 | 被动 | 缺页、除零、越界、trap(访管指令) |
| 外部中断 | 被动 | I/O 完成、时钟中断 |
关键理解:
- 从用户态到内核态的切换只能通过上述三种途径(系统调用/异常/外部中断)
- 访管指令(
trap)在用户态执行,但会触发切换到内核态 — 执行 ≠ 触发后的状态 - 一定要区分:调用指令在用户态,执行指令在内核态

切换流程(x86 为例):
用户程序执行 int 0x80(系统调用指令)
↓
CPU 自动:切换到 Ring 0(内核态),跳转到系统调用处理函数
↓
OS 执行相关服务
↓
执行 iret 返回用户程序
↓
CPU 自动:切回 Ring 3(用户态),恢复用户程序继续运行
系统调用
系统调用是用户态程序与 OS 内核之间的接口。



当应用程序需要执行特权操作(文件操作、网络通信、进程创建等)时,通过系统调用请求内核在内核态代为执行。
- 涉及特权级转换:用户态 → 内核态 → 用户态,有性能开销
- 常见类型:进程管理(fork/exec/wait)、文件操作(open/read/write)、内存管理、网络通信
- 系统调用通过库函数实现,不在用户程序代码中
- 系统调用一般不允许嵌套或递归

从内核转到用户只有 系统调用这一个法子?
审题的时候有想过,这个操作完成是指系统调用到内核态还是执行系统调用的内部程序,看完答案发现确实就是那么简单,但是其他选项还是要搞明白为什么不行

不同操作系统的系统调用接口不同
III 错误原因在于 Linux 与 Windows 的系统调用接口不同,例如创建进程分别对应 fork 和 CreateProcess。
系统调用 vs 过程调用


| 过程调用 | 系统调用 | |
|---|---|---|
| 是否引发中断 | 否 | 是(软中断) |
| CPU 模式切换 | 不切换(全程同一模式) | 用户态 → 内核态 |
| 需保存的内容 | 只保存 PC | 保存 PC + PSW |
| 被调用函数位置 | 在程序代码中 | 通过库函数,不在程序代码中 |
| 可否嵌套 | 可以 | 一般不允许 |
| 注意 PSW 存储的是 CPU 内核态 的标志 |
过程调用可以在用户态或内核态任一模式下发生,关键是不切换模式。
原语

处于 OS 最底层,由多条指令构成,不能被打断,运行时长较短,调用频繁。原语是内核态的原子操作。
内核架构与虚拟化
微内核 vs 宏内核
| 微内核 | 宏内核 | |
|---|---|---|
| 内核态运行 | 最少核心功能(进程/线程管理、低级存储器管理、中断处理) | 全部 OS 功能 |
| 用户态运行 | 文件系统、设备驱动、网络协议栈等 | 无 |
| 可靠性 | 高(驱动崩溃不影响系统,隔离好) | 低(一部分失败 → 整个系统崩溃) |
| 性能 | 稍低(频繁上下文切换和消息传递) | 高(同一地址空间直接通信) |
| 代表系统 | IOS、Fuchsia、HarmonyOS NEXT | Linux、Windows、Android、传统 UNIX |
- 微内核设计原则:“机制与策略分离” — 机制保留在微内核,策略由外部服务器实现
- 微内核性能低的原因:频繁的上下文切换(用户态↔内核态),而非内核代码本身慢

与虚拟化的关系
特权级扩展:
Ring -1 (VMX root mode) → Hypervisor / VMM(最高权限)
Ring 0 → OS 内核
Ring 3 → 用户程序
- 1 型 VMM:直接运行在硬件上,是真正的内核态;客户机 OS 通过 VMM 间接使用硬件。1 型 VMM 本身属于用户态程序但能间接调用硬件 — 无法一元论,重点看实际运行

- 2 型 VMM:运行在宿主机 OS 之上,作为用户态进程

总结
跨章节关联
-
进程管理:内核空间具有更高特权级别,对用户程序不可见;Idle 进程(PID 0)始终在内核态运行;线程模型分纯用户态/纯内核态/混合方案
-
内存管理:共享内存是最快的 IPC,无需进入内核态;
mmap消除用户态↔内核态的缓冲区拷贝;堆内存分配器(malloc/free)是动态分区思想下沉到用户态 -
I/O 管理:设备驱动程序运行在内核态,直接访问设备寄存器和端口;中断处理程序运行在内核态
-
文件管理:
read/write系统调用涉及用户态→内核态切换
记忆点
-
判断状态的唯一标准:有无执行特权指令的能力
-
访管指令 trap:在用户态执行,触发切换到内核态 — 执行 ≠ 触发后状态
-
系统调用需保存 PSW,过程调用只需保存 PC(因为系统调用要切换 CPU 模式)
-
微内核性能低 是因为频繁上下文切换,不是内核代码本身慢
-
中断发生后:CPU 自动切换到内核态,由中断处理程序在内核态执行
易错点
- 系统调用 ≠ 过程调用:前者切换 CPU 模式,后者不切换;前者需保存 PSW,后者只需保存 PC
- 1 型 VMM 的态:不能简单归为”用户态”或”内核态”,要看实际运行时特权指令能力
- 让权等待:只有阻塞(如信号量
wait)才能让出 CPU,while 循环忙等做不到让权
静态重定位 vs 动态重定位
考频:高 | 选择题常考
核心区别
| 静态重定位 | 动态重定位 | |
|---|---|---|
| 转换时机 | 装入时一次性 | 每次访问时实时 |
| 能否移动 | ❌ 地址锁死 | ✅ 更新寄存器 |
| 支持对换 | ❌ | ✅ |
记忆点
-
静态 = 焊死:地址硬编码,动不了 → 没法对换(并且静态重定位用的基地址是 随机空闲内存块的开头地址,不能自由分配)
-
动态 = 轮子:重定位寄存器(Base),物理地址 = 逻辑地址 + Base → 随便换
-
关键公式:
物理地址 = 逻辑地址 + Base
易错点
-
静态重定位可以用于多道程序,但会产生外部碎片
-
对换 vs 页面置换
| 对换(Swapping) | 页面置换(Page Replacement) | |
|---|---|---|
| 单位 | 整个进程(PCB + 全部页面) | 单个页面 |
| 时机 | 内存紧张时,把低优先级进程整体换出到磁盘 | 缺页时,内存满,选一个页面换出 |
| 实现条件 | 需要动态重定位 (利用PDBR, 进程要能移动) | 需要虚拟内存支持 |
分页存储管理
考频:极高 | 选择 + 综合
核心定义
将进程和内存都切成固定大小的块(页/页框),进程的页可以装入内存的任意页框。
内部碎片
分页会产生内部碎片,原因:
- 页大小固定(如4KB)
- 进程最后一页可能装不满
- 剩余空间无法利用,形成内部碎片
举例:进程大小17KB,页大小4KB
页0:4KB(满)
页1:4KB(满)
页2:4KB(满)
页3:4KB(只用1KB,内部碎片3KB)
碎片对比
| 分页 | 分段 | |
|---|---|---|
| 内部碎片 | 有(最后一页可能不满) | 无 |
| 外部碎片 | 无(页框可任意分配) | 有(连续分配导致) |
记忆点
-
分页 = 固定大小 → 有内部碎片
-
分段 = 可变大小 → 有外部碎片
请求分页机制
考频:极高 | 选择 + 综合
基本分页 vs 请求分页
| 基本分页 | 请求分页 | |
|---|---|---|
| 页表项内容 | 物理块号 | 物理块号 + Valid位 + 磁盘索引 |
| 地址转换 | 直接查表得块号 | 先看Valid位,=1则同基本分页,=0则触发缺页 |
| 物理地址公式 | 块号 × 页大小 + 偏移 | 块号 × 页大小 + 偏移(一样) |
| PTBR | 指向页表起始位置 | 指向页表起始位置(一样) |
| “请求”含义 | 无 | 用到哪页才调入哪页,不是装入时全部放入内存 |
缺页的判定逻辑
CPU访问虚拟地址
↓
TLB查找 → 命中 → 直接得到物理地址(无缺页)
↓ 未命中
查页表 → Valid=1 → 得到物理地址(无缺页)
↓ Valid=0 页表本身不在内存
触发缺页异常
结论:TLB和页表中都找不到有效映射 → 缺页。这两个是地址转换的全部途径,都没有就是缺页。
缺页处理的过程
发生缺页
↓
有空闲页框?
├── 是 → 直接装入(无需替换)
└── 否 → 先替换(换出一页腾空间)→ 再装入
注意
替换页面时,我们是在页表中找算法给定的页框(当前页面优先级比页框中之前装入的页面优先级要高)可以替换
替换是装入的前置步骤
页表作为页框中的数据
核心思想:页表本身也是页面,也占物理页框,也有虚拟地址
页表是"数据" → 存在某个物理页框中 → 这个页框对应一段虚拟地址
↑
页目录/上级页表的页表项指向这里
页表项的虚拟地址推算
题目特征:告诉你页表起始的虚拟地址,要求算出某个页表项的虚拟地址范围
万能解法:
已知:页表起始虚拟地址VA_start,页大小4KB,页表项4B
步骤:
1. 页表占多少页? → 页表总项数 = 每页能放的项数 = 4KB/4B = 1024项
2. 页表本身占几页? → 项数 × 4B / 页大小 = 1024×4B/4KB = 1页
3. 该页的虚拟页号 = VA_start对应的页号
4. 页表项i的虚拟地址 = VA_start + i × 4B
速算模板:
页表起始虚拟地址:0x00400000
页大小:4KB = 0x1000
页表项大小:4B
求第8个页表项的虚拟地址:
VA = 0x00400000 + 8 × 4 = 0x00400020
求该页表项所在的虚拟页号:
页号 = 0x00400020 >> 12 = 0x00400 → 即第1024页
多级页表的”递归”本质
页目录本身 → 也是页面 → 也有虚拟地址 → 也存在某个页框中
↓
页目录项指向的页表 → 也是页面 → 也有虚拟地址
↓
页表项指向的数据页 → 也是页面 → 也有虚拟地址
每一级都是一样的结构:虚拟地址 → 查表 → 得到下一级的物理地址
对换区 vs 文件区
教材三种调页来源
| 情况 | 页面来源 | 理论依据 |
|---|---|---|
| 对换区足够 | 全部从对换区调入 | 对换区连续分配,I/O更快 |
| 对换区不够 | 不修改的从文件区,修改的从对换区 | 节省对换区空间 |
| UNIX方式 | 首次从文件区,换出后放对换区 | 不预先拷贝,按需加载 |
实际OS的做法(Unix/Linux):
- 第一次访问 → 从文件区调入(因为页面还没被修改过)
- 换出后再调入 → 从对换区调入(因为已经是脏页)
- 加大对换区不影响调页速度:首次访问不走对换区,后续访问本来就走对换区
考试中的矛盾点(2014真题):
- 教材从理论出发:对换区大→调页快(因为页表可以从对换区调入)
- 出题从实际出发:实际OS首次访问走文件区,对换区大小不影响调页速度
- 结论:选项III(增大交换区)不能加快虚实地址转换,因为地址转换靠TLB+页表查找,跟对换区无关
分配策略 vs 替换策略
四种组合
| 局部替换(只能换自己的) | 全局替换(可以换别人的) | |
|---|---|---|
| 固定分配 | ✅ 合理 | ❌ 矛盾 |
| 可变分配 | ⚠️ 不常见 | ✅ 合理 |
唯一矛盾的组合:固定分配 + 全局替换
- 固定分配 = 每个进程页框数锁死
- 全局替换 = 可以从其他进程拿页框
- 两个前提互相打架,逻辑不通
应用场景
| 组合 | 应用 | 特点 |
|---|---|---|
| 固定分配 + 局部替换 | 实时系统 | 页框数确定,性能可预测 |
| 可变分配 + 全局替换 | 通用OS(Linux/Windows) | 灵活调整,实现简单 |
Belady 异常
定义
在某些页面置换算法(特别是 FIFO)中,增加页框数量反而导致缺页次数增加,违背”更多内存 → 更少缺页”的直觉,这种异常叫做 Belady 异常。
经典例子
页面访问序列:1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5
| 页框数 | FIFO 缺页次数 |
|---|---|
| 3 个页框 | 9 次 |
| 4 个页框 | 10 次(反而更多!) |
各类算法
| 算法 | 会出现 Belady 异常? | 原因 |
|---|---|---|
| FIFO | ❌ 会 | 不是栈算法,页框多时历史信息丢失,无法包容小容量的驻留集(混乱算法) |
| OPT | ✅ 不会 | 栈算法:k 帧的驻留集 ⊆ k+1 帧的驻留集 |
| LRU | ✅ 不会 | 同为栈算法,基于时间局部性 |
| CLOCK | ❌ 会 | CLOCK 算法是对LRU的近似,但不是严格的栈算法,它依赖访问位和指针扫描 |
记忆点
- Belady 异常 = FIFO 专属考点(OPT/LRU 这类栈算法不会出现)
- 栈算法的性质:页框越多,驻留集只会更大或不变 → 缺页单调不增
- FIFO 不满足栈性质:队头淘汰与”驻留时长”相关,与”未来是否使用”无关
分段存储管理
段地址说明
逻辑地址 = [段号S | 段内偏移W]
↓
段表项 = [基址 | 段长]
↓
越界检查:W >= 段长? → 是则越界中断(段错误)
↓
物理地址 = 基址 + W
逐步解释
第1步:拆分逻辑地址
- CPU给出的逻辑地址分两部分:段号S 和 段内偏移W
- 本题中 S占8位,W占24位
第2步:查段表
- 用段号S去查段表,找到对应的基址(段在物理内存的起始位置)和段长(该段有多大)
第3步:越界检查 ⚠️
- 如果偏移量W ≥ 段长,说明访问超出了该段的范围
- 触发段错误中断(就是程序崩溃时常见的 Segmentation Fault)
第4步:计算物理地址
- 通过检查后:物理地址 = 基址 + W
- 即从段的起点,偏移W个字节,就是实际的内存位置
段长的作用
越界检查(安全保护),不是用来计算地址
基址:计算物理地址 = 基址 + 段内偏移段长:确保段内偏移 < 段长,否则越界中断
分页 vs 分段
| 分页 | 分段 | |
|---|---|---|
| 大小 | 固定(如4KB) | 可变(程序实际大小) |
| 需要段长吗 | 不需要(每页都一样大) | 必须有(段大小不同) |
| 越界检查 | 页内偏移不可能越界 | 段内偏移可能越界 |
| 目的 | 内存利用率 | 信息共享和保护 |
记忆点:段长是安全锁,防止程序越界访问其他段的内存
动态分区
内存空闲分区表 类似 磁盘空闲分区表 表项包含:分区起始地址,分区大小。
内存回收规则
回收时检查是否相邻,相邻则合并,不相邻则新增。
| 情况 | 处理 | 分区数变化 |
|---|---|---|
| 与前一个空闲区相邻 | 合并 | -1 |
| 与后一个空闲区相邻 | 合并 | -1 |
| 与前后都相邻 | 三合一 | -2 |
| 与前后都不相邻 | 新增 | +1 |
典例(2017真题)
空闲分区:[20K,40KB] [500K,80KB] [1000K,100KB] [200K,200KB]
回收:起始60K,大小140KB(范围60K-199K)
解题步骤:
-
回收区60K-199K与空闲区20K-59K相邻 → 合并为20K-199K(180KB)
-
合并后20K-199K与空闲区200K-399K继续相邻(199K+1=200K)→ 三合一为20K-399K(380KB)
-
结果:3个分区 [20K,380KB] [500K,80KB] [1000K,100KB]
-
最佳适应按大小升序排序:链首 = 最小的 [500K, 80KB]
答案:B(3、500K、80KB)
偷鸡技巧
直接看起始地址判断是否相邻:
- 回收区起始地址 = 某空闲区起始地址 + 该空闲区大小 → 与该空闲区后邻
- 回收区起始地址 + 回收区大小 = 某空闲区起始地址 → 与该空闲区前邻
本题速算:
- 回收区起始60K,空闲区20K大小40KB → 20K+40K=60K → 后邻,合并
- 合并后结束199K,下一空闲区起始200K → 199K+1=200K → 继续相邻,三合一
注意事项
-
边界判断:
起始地址 + 大小是下一个块的起始,不是末尾地址 + 1 -
最佳适应会重新排序:题目说”每次回收后重新排序”,答案可能是按大小排序后的链首
-
别漏看”相邻”:回收区可能与多个空闲区同时相邻(前+后),要三合一
关联记忆
静态重定位 → 不能移动 → 不能对换 → 无虚拟内存
动态重定位 → 能移动 → 能对换 → 虚拟内存基础
↓
请求分页(页面置换)
↓
虚拟内存实现
文件管理
软硬链接 与 FCB
先说 FCB,原理上来说 FCB(文件控制块)是 目录 用来描述对应 文件的。
具体实现时,为了让用户能够高效调用文件,将 目录项(即 FCB)分割为两部分,实际目录项中只有 文件名 和 inode 号,另一部分放到了 索引表 中 (包含 文件类型、权限、所有者、文件大小、数据块指针 等)
正是因为这种现实中的 分割,给 软硬链接 的实现 铺垫了基础,
[硬链接]
不同文件名可以对应同一 inode 指向的文件,从而实现 共享同一份 文件数据
inode 内部维护着一个链接计数器,每创建一个硬链接,计数加一;删除一个文件名,计数减一;只有计数归零时,文件数据块才真正被释放。所以”删除文件”准确说是”删除一个目录项”
[软链接]
软链接 是一个独立的文件,有自己的 inode,文件内容存的是目标文件的路径字符串。所以软链接可以跨文件系统,但目标被删后软链接就悬空失效了;而硬链接不能跨文件系统,但任意一个链接都和原文件”平等”,没有主从之分
硬链接共享 inode,软链接存路径。
单个文件最大长度计算
2012年真题 - 直接索引 + 混合索引
题目条件:系统最大容量 4TB,块大小 1KB,FCB 索引表区 512B
(1) 直接索引结构
块号最少字节数 = ?
├─ 4TB = 2^42 B
├─ 最大块数 = 2^42 / 2^10 = 2^32 块
├─ 块号需要表示到 2^32,需32位 → 4字节
├─ 索引表项数 = 512B ÷ 4B = 128项
└─ 最大文件长度 = 128 × 1KB = 128KB
记忆点:直接索引 = 每个索引项指向一个块, 索引项数 = 文件最大块数
(2) 混合索引结构
(起始块号6B + 块数2B + 直接索引 504B)
原方案:
├─ 连续部分:块数2B → 最大 2^16-1 = 65535块
├─ 直接索引:504B ÷ 6B = 84个索引项
├─ 总块数 = 65535 + 84 = 65619块
└─ 最大文件长度 ≈ 64.08MB
优化方案(使文件最大):
├─ 起始块号改4B(够用,系统最大块号2^32只需4B)
├─ 块数改4B(能表示2^32 - 1块,但是官方答案给的是 2^32)
├─ 连续部分最大 = 2^32块(受系统容量限制)
├─ 直接索引:(512-8)B ÷ 6B = 84项
├─ 总块数 = 2^32 + 84
└─ 最大文件长度 ≈ 4TB + 84KB
关键:优化时要先保证块号够用(4字节),再考虑块数字段
2014年真题 - 链接分配
题目条件:每块 1KB,指针 4B
链接分配的文件最大长度:
├─ 指针4B → 可寻址 2^32 个块
├─ 每块实际存数据 = 1KB - 4B = 1020字节
├─ 最大文件长度 = 2^32 × 1020B = 4080GB
记忆点:链接分配的限制是指针的寻址能力,不是块数
三种分配方式对比
| 分配方式 | 文件最大长度限制因素 | 本题最大长度 |
|---|---|---|
| 连续分配 | 磁盘连续空间大小 | 取决于最大连续空闲区 |
| 链接分配 | 指针位数(寻址能力) | ≈4.08GB(4B指针,2进制换算) |
| 索引分配 | 索引表项数 × 块大小 | 128KB(直接索引) |
易错点:
- 链接分配计算时,要减去指针占用空间再乘块数
- 索引分配要考虑索引表本身的大小限制
- 优化混合索引时,块号字段优先保证够用(系统最大块数 = ,需 4 字节)
操作系统初始化与磁盘结构
核心结论
磁盘物理格式化 → 建立 扇区 + 磁道
磁盘分区 → 建立 磁盘分区表 + 引导扇区
磁盘逻辑格式化 → 建立 根目录 + inode表 (同文件系统有关)
操作系统初始化 → 建立 中断向量表(BIOS相关)
四个阶段详解
1. 物理格式化
出厂前由厂商完成,把盘片划分为磁道、扇区。 用户买到硬盘时这一步已经做好了
2. 硬盘分区
把硬盘划分为若干独立区域,如 C 盘、D 盘。
一块硬盘
├── 分区1(C盘)
├── 分区2(D盘)
└── 分区3(D盘)
此时建立的是分区表——记录每个分区从哪里开始、到哪里结束。
3. 逻辑格式化
也称为 文件系统 格式化(软件层面)
对每个分区单独进行,选择文件系统类型( 等)。
类比:右键U盘 → 格式化 → 选择 NTFS,就是在做这一步。
格式化在分区内部建立两样东西:
根目录
- 你打开U盘/C盘看到的那个最外层的空文件夹界面
- 所有文件和文件夹都挂在它下面
- 格式化会把旧的根目录清空重建
inode 表
根目录(你能看见) inode表(看不见)
──────────────── ─────────────────
📁 我的照片/ #001 我的照片 → 位置第38块
📄 photo1.jpg → #002 photo1.jpg → 大小3MB 位置第39块
📄 photo2.jpg #003 photo2.jpg → 大小2MB 位置第42块
根目录负责展示文件结构,inode表负责记录文件的真实信息,缺一不可。
4. 操作系统初始化
每次开机都要做
内核加载进内存后,正式运行前的准备工作
BIOS 负责初始化硬件,然后建立 中断向量表
中断向量表是什么? 支撑操作系统的内核
- 存放各类中断的处理程序入口地址
- 操作系统一切运行都依赖中断(I/O、系统调用、异常处理……)
- 没有它,操作系统无法响应任何事件
- 每次开机都要重新建立(存在内存里,不是磁盘)
真题回顾

答案:A
| 选项 | 建立时机 | 是否每次开机重建 |
|---|---|---|
| A 中断向量表 | 操作系统初始化 | ✅ 是 |
| B 文件系统根目录 | 逻辑格式化 | ❌ 否 |
| C 硬盘分区表 | 硬盘分区 | ❌ 否 |
| D inode表 | 逻辑格式化 | ❌ 否 |
易错点
前三个阶段(物理格式化、分区、逻辑格式化)建立的结构持久化存在磁盘上,开机后只是读取,不会重新创建。
只有中断向量表是每次开机时由操作系统初始化阶段重新建立的。
磁头读取数据的物理原理
考频:中 | 选择题偶尔考,综合题考
硬盘结构
盘片(高速旋转)
↑
磁头(悬浮在盘片上方,不接触)
↑
磁臂(控制磁头径向移动)

读取原理
盘片表面涂满磁性材料,每个微小区域的磁极方向代表 0 或 1:
↑ 磁极朝上 = 1
↓ 磁极朝下 = 0
磁头里有一个感应线圈,当盘片旋转,磁性区域从磁头下方划过时:
磁场变化 → 线圈产生感应电流 → 电流大小/方向 → 解读为0或1
这就是电磁感应,和初中物理一样的原理。
写入原理
反过来:
给线圈通电 → 产生磁场 → 改变盘片上该区域的磁极方向 → 写入0或1
为什么磁头不接触盘片
盘片转速极高(7200转/分),接触会划伤盘片,所以磁头悬浮在纳米级高度,靠气流维持间距。
这也是为什么硬盘怕震动——震动可能导致磁头撞上盘片,即磁头划伤(head crash),数据全毁。
何为访问
读一次是访问,写一次也是访问;
与 磁盘的内容是否从磁盘到主存再从主存到磁盘这一连续过程 无关!!!
进程同步与互斥
错题整理
【2016】进程互斥与线程并发
题目: 进程P1和P2均包含并发执行的线程,部分伪代码描述如下所示。
伪代码:
// 进程 P1
int x = 0;
Thread1() {
int a;
a = 1;
x += 1;
}
Thread2() {
int a;
a = 2;
x += 2;
}
// 进程 P2
int x = 0;
Thread3() {
int a;
a = x;
x += 3;
}
Thread4() {
int b;
b = x;
x += 4;
}
问题: 下列选项中,需要互斥执行的操作是()。
A. a = 1 与 a = 2
B. a = x 与 b = x
C. x += 1 与 x += 2
D. x += 1 与 x += 3
正确答案: C
要点:
- 进程局部:每个进程有自己的局部变量
a、b,但x是共享变量 - 核心理解:只有对共享变量
x的并发操作才需要互斥
【2018】让权等待
题目: 下列同步机制中,可以实现让权等待的是()。
A. Peterson 方法
B. swap 指令
C. 信号量方法
D. TestAndSet 指令
正确答案: C
要点:
- while 循环做不到让权:Peterson、swap、TestAndSet 均使用 while 循环检测,进程在循环中忙等
- 只有涉及 CPU 才能使进程阻塞离开:信号量方法中的
wait()操作可使进程阻塞
【2016】TSL 指令实现互斥
题目: 使用 TSL(TestandSetLock)指令实现进程互斥的伪代码。
do {
while (TSL(&lock))critical section;
lock = FALSE;
} while (TRUE);
A. 退出临界区的进程负责唤醒阻塞态进程
B. 等待进入临界区的进程不会主动放弃CPU
C. 上述伪代码满足“让权等待”的同步准则
D. while(TSL(&lock))语句应在关中断状态下执行
正确答案: B(等待进入临界区的进程不会主动放弃 CPU)
要点:
- 死等:进程在
while循环中持续调用 TSL,属于忙等 - while 循环出不来了:若 lock 为 TRUE,进程会一直循环检测
【2014】管道通信
题目: 下列关于管道(Pipe)通信的叙述中,正确的是()。
A. 一个管道可实现双向数据传输
B. 管道的容量仅受磁盘容量大小限制
C. 进程对管道进行读操作和写操作都可能被阻塞
D. 一个管道只能有一个读进程或一个写进程对其操作
正确答案: C(进程对管道进行读操作和写操作都可能被阻塞)
要点:
- 单项半双工:管道通常是半双工(单向)通信
- 内存相关:管道容量受内存大小限制,而非磁盘
- 可以多个写:允许多个写进程
【2010】进程创建
题目: 下列选项中,导致创建新进程的操作是()。
I. 用户登录成功 II. 设备分配 III. 启动程序执行
A. 仅I、II
B. 仅II、III
C. 仅I、III
D. I、II、III
正确答案: C(仅 I、III:用户登录成功、启动程序执行)
要点:
- 分时 创建新进程:用户登录成功(分时系统)会创建新进程
- 设备分配:只是资源分配,不创建新进程
同步机制准则
- 空闲让进:临界区空闲时,允许一个进程立即进入
- 忙则等待:已有进程进入临界区时,其他进程必须等待
- 有限等待:保证进程在有限时间内进入临界区
- 让权等待:进程不能进入临界区时,应立即释放处理机(不一定要实现)

很有意思
软件实现方法
| 方法 | 特点 | 问题 |
|---|---|---|
| 单标志法 | 两个进程交替进入 | 可能违背空闲让进 |
| 双标志先检查 | 先检查对方标志 | 可能同时进入,违背忙则等待 |
| 双标志后检查 | 先设置自己标志 | 双方互相谦让,导致饥饿 |
| Peterson算法 | 标志+turn变量 | 仍属于忙等 |
硬件实现方法
| 方法 | 特点 |
|---|---|
| Test-and-Set | 原子操作,忙等锁 |
| Swap指令 | 原子操作,忙等锁 |
| 关中断 | 仅适用于单处理器 |
易错点
- 局部变量 vs 共享变量:不同进程中的同名变量是独立的,只有共享变量需要互斥
- 让权等待:只有阻塞(如信号量
wait)才能让出 CPU - 管道容量:受内存限制,非磁盘
- 进程创建:设备分配不创建新进程
进程状态切换
状态切换的原因
| 切换方向 | 原因 | 主动/被动 |
|---|---|---|
| 就绪 → 运行 | 被进程调度选中,获得 CPU | 被动(调度器决定) |
| 运行 → 就绪 | 时间片用完;被更高优先级进程抢占 | 被动(CPU 被剥夺) |
| 运行 → 阻塞 | 请求 I/O、申请资源失败、wait() 信号量 | 主动(自己发起等待) |
| 阻塞 → 就绪 | I/O 完成、资源释放、signal() 唤醒 | 被动(事件发生,他人唤醒) |
判断口诀:看进程缺什么
-
只缺 CPU → 就绪态
-
缺 CPU 以外的资源(等事件)→ 阻塞态
典型阻塞事件:请求 I/O、等待信号量、等待消息、申请临界资源失败
时间片轮转 与 阻塞态
这是最容易混淆的一对关系,真题反复考:
| 对比项 | 运行 → 就绪(时间片轮转) | 运行 → 阻塞 |
|---|---|---|
| 触发原因 | 时间片用完、被抢占 | 等待某事件(I/O、信号量) |
| 进程意愿 | 还想继续执行 | 主动放弃 CPU 去等待 |
| 缺少资源 | 只缺 CPU,不缺任何其他资源 | 缺 CPU 以外的资源 |
| 恢复条件 | 重新调度即可,随时能跑 | 必须等事件发生才被唤醒 |
核心结论:时间片用完,进程进入就绪态(就绪队列尾部),绝不进入阻塞态。
时间片大小的权衡
- 时间片太短:切换次数 = 变多,系统开销(上下文切换)增大
- 时间片太长:响应时间变差,退化为 FCFS
- 影响因素:响应时间、系统开销、进程数量()
时钟中断的作用:RR 算法靠时钟中断计时,中断发生后修改当前进程的剩余时间片,减到 0 则触发调度
【真题】时间片调度(第 26 题)
题目: 下列有关基于时间片的进程调度的叙述中,错误的是()。
A. 时间片越短,进程切换的次数越多,系统开销也越大
B. 当前进程的时间片用完后,该进程状态由执行态变为阻塞态
C. 影响时间片大小的主要因素包括响应时间、系统开销和进程数量等
D. 时钟中断发生后,系统会修改当前进程在时间片内的剩余时间
正确答案: B
要点:
- B 错误(题眼):时间片用完,进程不缺任何资源,只是 CPU 被剥夺,转为就绪态回到就绪队列尾部;阻塞必须由”等待事件”引起
- A 正确:切换次数随时间片缩短而增多,上下文切换开销变大
- C 正确:响应时间、系统开销、进程数量共同决定时间片取值
- D 正确:RR 靠时钟中断计时并修改剩余时间片
【2015】死锁避免 vs 死锁检测
题目: 若系统 S1 采用死锁避免方法,S2 采用死锁检测方法。下列叙述中,正确的是()。
I. S1 会限制用户申请资源的顺序,而 S2 不会
II. S1 需要进程运行所需的资源总量信息,而 S2 不需要
III. S1 不会给可能导致死锁的进程分配资源,而 S2 会
A. 仅 I、II B. 仅 II、III C. 仅 I、III D. I、II、III
正确答案: B
要点:
- I 错误:限制申请资源顺序是死锁预防(破坏循环等待条件)的手段,避免法不限制顺序
- II 正确:死锁避免(银行家算法)必须预知进程的最大资源需求;检测法只需当前分配情况
- III 正确:避免法只在系统处于安全状态时才分配;检测法照常分配,死锁发生后再检测并解除
三种处理策略层次:
| 策略 | 时机 | 手段 | 代价 |
|---|---|---|---|
| 死锁预防 | 事前(静态) | 破坏四个必要条件之一(如限制申请顺序) | 资源利用率低 |
| 死锁避免 | 事中(动态) | 银行家算法,需资源总量信息 | 每次分配都要安全性检查 |
| 检测+解除 | 事后 | 资源分配图检测,剥夺/撤销进程 | 死锁已发生,有损失 |
易错点
- 时间片用完进就绪,不进阻塞:判断标准是”缺不缺 CPU 以外的资源”
- 阻塞是主动行为:运行中的进程自己请求资源失败才阻塞;被唤醒是被动的
- 限制申请顺序的是预防,不是避免:避免法(银行家算法)只看安全性,不限顺序
- 银行家算法需要 Max 信息:检测法不需要进程未来的资源需求
- 管程是啥,管程为啥,管程干啥
- 编程语言不要局限于 c python java 实际上的编程语言范围及其宽广

看这个就行了

死锁的必要性条件:每个阻塞进程都少一个资源,构成一个资源需求环
