设备分配与回收
这一节回答:进程说”我要用打印机”,系统凭什么、按什么步骤把设备交给它。
本节的四张控制表是全章公认最难记的部分。难记的原因是它们通常被当成四组字段来背——但它们其实是一条指针链,而这条链的形状完全由一个事实决定:一次 I/O 需要设备、控制器、通道三样同时到位,缺一不可。 抓住这一点,四张表的存在理由、字段构成和分配步骤全都能推出来。
机制
设备分配要考虑什么
① 设备的固有属性。 独占设备、共享设备、虚拟设备三类,分配策略完全不同:独占设备只能整台给一个进程,共享设备可以多个进程交替使用,虚拟设备则由 SPOOLing 造出来。
② 设备分配算法。 常用先来先服务和优先级高者优先,与进程调度算法同源。
③ 设备分配的安全性。 即这样分会不会导致死锁。
疑问点:不属于设备分配考虑因素的选项
- 在下列问题中,( )不是设备分配中应考虑的问题。 A. 及时性 B. 设备的固有属性 C. 设备独立性 D. 安全性
答案 A。 这道题的四个选项看起来”都挺像”,判据在于它们是不是设备分配这一步要做的决定:
B 固有属性决定了能不能独占——是分配前必须先判断的事。D 安全性决定了这样分会不会死锁——是分配时必须评估的事。C 设备独立性决定了逻辑名映射到哪台物理设备——正是分配要选出那一台(见 5.2.1)。
A 及时性关心的是”I/O 请求能不能在规定时间内被响应”,这是实时系统的调度指标或 I/O 性能指标,与”把哪台设备交给谁”这个决定无关。
安全分配方式与不安全分配方式
这一组是按”进程提出 I/O 请求后还能不能继续跑”来划分的:
安全分配方式——进程发出 I/O 请求后立即进入阻塞态,直到 I/O 完成才被唤醒。因此一个时段内每个进程最多只占用一台设备。
优点是不会死锁:进程在等待 I/O 时不再申请新设备,破坏了”请求和保持”条件。缺点是 CPU 与 I/O 设备串行工作,进程推进慢。
不安全分配方式——进程发出 I/O 请求后仍继续运行,还可以接着发出第二个、第三个请求,只有当它请求的设备已被别人占用时才阻塞。
优点是一个进程可以同时操作多个设备,推进迅速;缺点是可能死锁——它恰好满足了”请求和保持”。
名字里的”安全”指的就是”不会死锁”,与数据是否安全无关。
静态分配与动态分配
这一组是按”什么时候分”来划分的:
静态分配——在进程运行前一次性分配它所需的全部设备、控制器和通道,一旦分配就一直归它使用,直到进程撤销才释放。
它同样破坏了”请求和保持”条件,因而不会死锁,但设备利用率极低——一台设备可能整个进程生命周期里只用了几秒钟,却被独占到最后。
动态分配——进程运行过程中按需分配,用完立即释放。利用率高,但可能死锁。
规律是一致的:凡是”提前一次性拿够”的方案都不会死锁,代价都是利用率低。 这与 2.4.2 死锁预防中破坏”请求和保持”条件的做法是同一件事。
四张控制表:为什么是四张
疑问点:设备控制表的结构难以理解与记忆
设备控制表的内容较复杂,难以理解,也记不住。
先解决”为什么要有这些表”,字段就不用背了。
关键事实只有一条:一次 I/O 要走完 “通道 → 控制器 → 设备”这条完整路径,因此必须三样同时空闲,只要有一样被占用,这次 I/O 就走不通。
既然三样都是可能被占用的资源,就三样都要有一张表来记录”我忙不忙、谁在等我”。 于是有了 DCT(设备)、COCT(控制器)、CHCT(通道) 三张表;再加上一张 SDT(系统设备表) 作为总目录,用来从设备名找到对应的 DCT。
graph TD SDT["<b>SDT 系统设备表</b><br/>全系统唯一 · 总目录<br/><i>记录所有设备,指向各自的 DCT</i>"] DCT["<b>DCT 设备控制表</b><br/>每台设备一张<br/>① 我是谁:设备类型 / 标识符<br/>② 我忙不忙:设备状态<br/>③ 谁在等我:设备队列队首指针<br/>④ 我接在谁身上:→ COCT 指针"] COCT["<b>COCT 控制器控制表</b><br/>每个控制器一张<br/>状态 · 等待队列 · <b>→ CHCT 指针</b>"] CHCT["<b>CHCT 通道控制表</b><br/>每个通道一张<br/>状态 · 等待队列"] SDT -->|按设备名查到| DCT DCT -->|沿指针向上| COCT COCT -->|沿指针向上| CHCT classDef top fill:#fef3c7,stroke:#d97706,color:#78350f classDef mid fill:#dbeafe,stroke:#2563eb,color:#1e3a8a classDef bot fill:#dcfce7,stroke:#16a34a,color:#14532d class SDT top class DCT mid class COCT,CHCT bot
DCT 不需要背字段,它只回答四个问题:
① 我是谁(设备类型、设备标识符) ② 我忙不忙(设备状态:忙 / 闲) ③ 谁在等我(设备队列的队首指针) ④ 我接在谁身上(指向控制器控制表的指针)
COCT 和 CHCT 的结构与 DCT 完全同构,也是”我忙不忙 + 谁在等我 + 我接在谁身上”,只是最后一项 CHCT 没有(通道已经是最上面一级,再往上就是 CPU 了)。
所以四张表真正需要记的只有两件事:
第一,每张表都记”状态 + 等待队列”——因为它们都是可能被抢占的资源。
第二,每张表都有一个”向上的指针”——因为分配了设备还不够,必须顺着指针把它所连的控制器和通道一并拿到手。这条指针链就是分配步骤的路线图。
设备分配的步骤
有了那条指针链,分配步骤就是照着它走一遍:
① 根据物理设备名查 SDT,找到该设备的 DCT。
② 查 DCT 的状态。 若设备忙,把进程 PCB 挂到该设备的等待队列上;若空闲,把设备分配给进程。
③ 沿 DCT 中的指针找到 COCT,查控制器状态。 忙则挂到控制器的等待队列,空闲则分配。
④ 沿 COCT 中的指针找到 CHCT,查通道状态。 忙则挂到通道的等待队列,空闲则分配。
⑤ 设备、控制器、通道三者都分配到手,才能启动 I/O。
回收时反向进行:释放通道、控制器、设备,并唤醒各自等待队列上的进程。
一句话记法:从 SDT 找设备,查 DCT 分设备,沿指针查 COCT 分控制器,再沿指针查 CHCT 分通道;有一样忙,就挂到那一样的等待队列上。
边界
为什么必须三样都分配到才能启动
这是四张表存在的全部理由,也是最容易被忽略的一点。
数据要从设备走到内存,必须经过控制器和通道——这条路径上任何一段被别人占用,数据就过不来。所以哪怕设备本身是空闲的,只要它所连的控制器正忙着为另一台设备服务,这次 I/O 也启动不了。
这也解释了为什么等待队列有三个而不是一个:进程可能卡在三个不同的地方,系统必须知道它到底在等什么,才能在对应资源释放时唤醒正确的进程。
独占设备与共享设备的分配方式
疑问点:独占设备与共享设备的说法辨析
- 下面关于独占设备和共享设备的说法中,不正确的是( )。 A. 打印机、扫描仪等属于独占设备 B. 对独占设备往往采用静态分配方式 C. 共享设备是指一个作业尚未撤离,另一个作业即可使用,但每个时刻只有一个作业使用 D. 对共享设备往往采用静态分配方式
答案 D。
A 对:打印机、扫描仪一旦被一个作业用上,中途插进另一个作业就会把输出搅乱,因此必须独占。
B 对:独占设备正因为不能中途易主,才适合静态分配——运行前一次性给足,用到进程结束。这样虽然利用率低,但避免了死锁,对这类设备是合算的。
C 对:这正是”宏观上同时、微观上交替”的准确表述,与 5.1.1 那道题的结论一致。
D 错:共享设备恰恰应该采用动态分配。 共享设备(如磁盘)本来就允许多个进程交替使用,若也搞静态分配、让一个进程从头独占到尾,共享就无从谈起了。
判据可以概括为:不能中途易主的用静态分配,能中途易主的用动态分配。
“安全分配”与”静态分配”不是同一组概念
两者都能避免死锁,容易被当成一回事,但切分角度不同:
安全 / 不安全问的是”进程提出 I/O 请求后还能不能继续运行”。
静态 / 动态问的是”设备是运行前一次性分完,还是运行中按需分配”。
它们避免死锁的机制其实相同——都是破坏”请求和保持”条件,但破坏的方式不同:安全分配方式让进程”在等 I/O 时不再提新请求”;静态分配让进程”一开始就把所有要的都拿齐,之后不再提请求”。
同一台机器上两组概念可以自由组合,它们不是同义词。
设备分配与进程调度的相似性
四张表的分配逻辑与进程调度高度相似:都是”查资源状态 → 空闲则分配、忙则排队 → 释放时唤醒队首”。
差别在于设备分配要一次拿齐三样资源,而这正是死锁的温床——一个进程拿到了设备在等控制器,另一个进程拿到了控制器在等设备,就是典型的循环等待。
理解这一点,就能明白为什么设备分配这一节要专门讨论”安全性”,而进程调度那一节不必。
对照速查
| 设备分配要考虑的三项 | |
|---|---|
| ① | 设备的固有属性(独占 / 共享 / 虚拟) |
| ② | 设备分配算法(FCFS、优先级) |
| ③ | 设备分配的安全性(会不会死锁) |
| 不考虑 | 及时性(那是实时调度或性能指标) |
| 安全分配方式 | 不安全分配方式 | |
|---|---|---|
| 提出请求后 | 立即阻塞 | 继续运行,可再提请求 |
| 同时用几台设备 | 一台 | 多台 |
| 会死锁吗 | 不会(破坏请求和保持) | 可能 |
| 代价 | CPU 与 I/O 串行 | — |
| 静态分配 | 动态分配 | |
|---|---|---|
| 何时分 | 运行前一次性分完 | 运行中按需分 |
| 何时还 | 进程撤销时 | 用完立即释放 |
| 会死锁吗 | 不会 | 可能 |
| 利用率 | 低 | 高 |
| 适用 | 独占设备 | 共享设备 |
| 四张表 | 数量 | 记什么 |
|---|---|---|
| SDT 系统设备表 | 全系统一张 | 所有设备,指向各自的 DCT |
| DCT 设备控制表 | 每台设备一张 | 我是谁 / 我忙不忙 / 谁在等我 / → COCT |
| COCT 控制器控制表 | 每个控制器一张 | 状态 / 等待队列 / → CHCT |
| CHCT 通道控制表 | 每个通道一张 | 状态 / 等待队列 |
| 分配步骤 | 查哪张表 |
|---|---|
| ① 按设备名找到设备 | SDT |
| ② 分配设备 | DCT(忙则挂设备等待队列) |
| ③ 分配控制器 | COCT(忙则挂控制器等待队列) |
| ④ 分配通道 | CHCT(忙则挂通道等待队列) |
| ⑤ 三者齐备才能启动 I/O |
考点
- 设备分配考虑固有属性、分配算法、安全性;“及时性”不是
- 安全分配方式 = 请求后立即阻塞 = 不会死锁但 CPU 与 I/O 串行
- 静态分配适合独占设备,动态分配适合共享设备(真题选项 D 的错处)
- 四张表的共同结构:状态 + 等待队列 + 向上的指针
- DCT 四问:我是谁 / 我忙不忙 / 谁在等我 / 我接在谁身上
- 分配顺序 SDT → DCT → COCT → CHCT,三者齐备才能启动
- 三个等待队列的存在理由:进程可能卡在三个不同的地方
链接
- 🏠 返回总览:操作系统第 5 章:输入/输出管理总览
- ⬅️ 上一节:5.2.2 高速缓存与缓冲区
- ➡️ 下一节:5.2.4 SPOOLing 技术
- 🔗 硬件路径的三级结构,见 5.1.1 I/O 设备
- 🔗 破坏”请求和保持”条件,见 2.4.2 死锁预防
- 📖 名词库:第 5 章名词库