Appearance
题目
键盘中断服务例程执行结束时,所输入的数据存放位置是( )。
错因
A
把"中断服务例程结束"和"用户进程 read 系统调用结束"两个时刻混为一谈。ISR 结束只意味着数据从硬件搬到了内核,还没复制到用户进程——必须等用户态的进程主动调用 read(fd, buf, n),才会通过 copy_to_user 把数据从内核缓冲区送到用户的 buf。如果 ISR 自己直接送到用户缓冲区,会有大问题:ISR 在中断上下文中跑,不知道哪个用户进程在等这条数据,也不能持有任意进程的页表。
B
以为数据"暂存在 CPU 通用寄存器里"。ISR 进入和退出会做现场保存/恢复,寄存器最终要还给被中断的程序——如果 ISR 把数据留在寄存器里,恢复现场就会被覆盖。寄存器只是搬运过程的临时中转,最终落地必须是内存,而非寄存器。
D
以为 ISR "只是收到中断信号、ack 一下就返回"——数据还停在键盘控制器。但若数据不立即搬走,下一次按键会让控制器的数据寄存器被覆盖(控制器内只有几字节缓冲),数据就丢了。ISR 的核心工作恰恰是"在数据被覆盖前抢救出来"——搬到内核内存,让控制器寄存器腾空准备接收下一次输入。
总解析
核心:中断服务例程(ISR)的设计原则是**"快进快出"——只做必须立刻做的硬件搬运,把数据从设备控制器寄存器搬到内核内存(内核缓冲区)**就返回。更复杂的处理(语义解析、唤醒进程、复制到用户态)交给上层。
完整数据流(按键 → 应用程序拿到字符):
| 阶段 | 谁做 | 数据所在位置 |
|---|---|---|
| ① 物理层 | 键盘硬件 + 控制器 | 控制器的数据缓冲寄存器 |
| ② 中断处理(ISR) | OS 内核 ISR | 从硬件寄存器 → 内核缓冲区 ✓ |
| ③ 设备无关层 | OS I/O 软件 | 内核缓冲区(已在此) |
| ④ 用户层 read() | 系统调用,copy_to_user | 用户缓冲区 |
ISR 结束的瞬间:刚刚执行完搬运动作 → 数据就在内核缓冲区。还没等到用户进程发起 read,所以还没到用户缓冲区;现场已恢复,所以也不在寄存器里;硬件寄存器已被读空,所以也不在控制器。
逐项核对:
| 选项 | 数据是否在此 | 理由 |
|---|---|---|
| A 用户缓冲区 | ✗ | 需要等 read() 系统调用的 copy_to_user 才会到这里 |
| B CPU 通用寄存器 | ✗ | 仅作中转,ISR 退出前会恢复现场 |
| C 内核缓冲区 | ✓ | ISR 的搬运目的地,结束时数据正好落于此 |
| D 键盘控制器数据缓冲区 | ✗ | ISR 已经把数据搬走了,控制器寄存器腾空准备下一次输入 |
速记:ISR 把数据从硬件寄存器抢救到内核缓冲区——前后两端都不归它管:之前是硬件、之后是用户进程发起 read 才会动。
最终答案是 C。