Appearance
题目
进程 P 通过执行系统调用从键盘接收一个字符的输入,已知此过程中与进程 P 相关的操作包括:
- ① 将进程 P 插入就绪队列
- ② 将进程 P 插入阻塞队列
- ③ 将字符从键盘控制器读入系统缓冲区
- ④ 启动键盘中断处理程序
- ⑤ 进程 P 从系统调用返回
- ⑥ 用户在键盘上输入字符
编号 ①~⑥ 仅用于标记操作,与操作的先后顺序无关。
请回答下列问题:
(1) 按照正确的操作顺序,操作 ① 的前一个和后一个操作分别是上述操作中的哪一个?操作 ⑥ 的后一个操作是上述操作中的哪一个?
(2) 在上述哪个操作之后 CPU 一定从进程 P 切换到其他进程?在上述哪个操作之后 CPU 调度程序才能选择进程 P 执行?
(3) 完成上述哪个操作的代码属于键盘驱动程序?
(4) 键盘中断处理程序执行时,进程 P 处于什么状态?CPU 处于内核态还是用户态?
解析
先把整条时间线理出来
读一个键盘字符的完整流程:
P 调用 read() (系统调用 → 进入内核)
↓
[发现键盘缓冲区无字符]
↓
② 把 P 插入阻塞队列 ← P 阻塞在等待 I/O 上
↓
[调度其他进程运行]
↓
⋯⋯ 时间流逝 ⋯⋯
↓
⑥ 用户按下键盘
↓
键盘控制器收到字符 → 发出键盘中断
↓
④ 启动键盘中断处理程序 ← 当前 CPU 上的进程被打断进内核
↓
③ 字符从键盘控制器读入系统缓冲区
↓
① 把 P 从阻塞队列移到就绪队列
↓
[中断处理结束,返回原被打断进程或调度新进程]
↓
⋯⋯ 等到 P 被调度选中 ⋯⋯
↓
⑤ P 从系统调用返回(拿到字符,回到用户态)所以正确顺序:② → ⑥ → ④ → ③ → ① → ⑤
| 时序 | ② | ⑥ | ④ | ③ | ① | ⑤ |
|---|
(1)顺序问题
| 问 | 答 |
|---|---|
| 操作 ① 的前一个操作 | ③(先把字符存进缓冲区,才能把 P 唤醒到就绪队列) |
| 操作 ① 的后一个操作 | ⑤(P 被唤醒、调度选中后才能从系统调用返回) |
| 操作 ⑥ 的后一个操作 | ④(用户输入触发键盘中断 → 启动中断处理程序) |
编者注(易错点):
- ⑥ 的下一个不是 ③——③ 是中断处理程序里的一步,必须先 ④ 启动中断处理才能轮到 ③。中间不能跳过 ④。
- ① 的下一个不是 ⑥——⑥ 早就发生过了。① 之后 P 在就绪队列等,还要等到 CPU 调度选中它才执行 ⑤。
(2)调度切换问题
问 1:哪个操作之后 CPU 一定从 P 切换到其他进程?
答:② 之后。
P 调用 read() 时键盘缓冲区还是空的(因为 ⑥ 还没发生)→ P 主动把自己挂到阻塞队列上(操作 ②)。P 一旦阻塞,CPU 必然要选别的进程跑——不可能让 CPU 空转等几秒钟、几分钟、甚至几天等用户按键。
问 2:哪个操作之后 CPU 调度程序才能选择 P 执行?
答:① 之后。
调度程序只从就绪队列挑进程。P 被插入就绪队列(操作 ①)之前是在阻塞队列里——调度程序不会看阻塞队列。① 完成后 P 才"对调度可见"。
编者注(核心概念):进程的"就绪 / 阻塞"二态性是这道题的灵魂。
队列 进入 离开 调度可见? 就绪队列 创建 / 阻塞被唤醒 / 时间片用完 调度选中 → 运行 ✅ 阻塞队列 等 I/O / wait() / 信号量 P() 失败 I/O 完成 / signal() 唤醒 ❌ 题目里 ② 把 P 推下舞台、① 把 P 重新拉回观众席(候选名单)、⑤ 才是 P 真正再上台演出。
(3)哪个操作属于键盘驱动程序?
答:③(把字符从键盘控制器读入系统缓冲区)
设备驱动程序的职责:屏蔽设备硬件细节、向上提供统一的读写接口。具体到键盘驱动 = "和键盘控制器打交道、读出寄存器里的字符、放到系统缓冲区"——正是 ③ 干的事。
其它操作的归属:
| 操作 | 归属 |
|---|---|
| ① 插就绪队列 | 内核进程管理 / 调度子系统 |
| ② 插阻塞队列 | 内核进程管理(系统调用处理) |
| ④ 启动键盘中断处理程序 | 中断管理子系统(不是驱动本身,而是驱动的"入口") |
| ⑤ 系统调用返回 | 系统调用陷入 / 返回机制 |
编者注(易错点):很多同学会把 ④ 也算成驱动——其实 ④ 是中断框架启动驱动,相当于"敲门",门后才是驱动。中断处理程序里的"读寄存器"那一段才是驱动代码。408 题这种细微区分要分清楚。
(4)中断处理时 P 的状态 + CPU 模式
P 的状态:阻塞
中断发生在 ⑥ 之后、① 之前——这段时间 P 还在阻塞队列里。直到 ① 把 P 转到就绪队列,P 才变成 ready;再到调度选中、⑤ 返回时才回到 running。
CPU 模式:内核态
中断处理是内核代码(保护现场、执行中断服务、调度判断、恢复现场),全程在内核态运行。即使被中断的进程之前是用户态,一旦进入中断处理程序,CPU 立刻切到内核态。
编者注(一句话总结):中断处理 = 内核态干活;进程状态独立于 CPU 模式。
P 是阻塞状态,和 CPU 当前是内核态还是用户态没关系——P 此刻没在 CPU 上跑,CPU 正在跑别人或在跑中断处理代码。
这两个概念混淆是 OS 章节的"高频丢分点":进程状态描述"进程自己在不在跑";CPU 模式描述"当前 CPU 上的代码权限多高"。