让硬件事件安全进入内核,并把具体设备收成统一接口。
| 设备事件 | 如果没有中断 / 驱动 | 被迫设计 |
|---|---|---|
| 键盘输入 | 应用一直轮询,CPU 被浪费 | 中断 handler 把字符放入输入缓冲区 |
| 磁盘 IO 完成 | 等待进程不知道何时恢复 | 驱动完成请求,唤醒 blocked 进程 |
| 网络包到达 | 应用直接碰网卡队列,安全和共享失控 | 内核收包,放入 socket 缓冲区 |
| 定时器 tick | 死循环程序不让出 CPU | 定时器中断触发调度 |
| 阶段 | 内核动作 | 注意点 |
|---|---|---|
| 硬件发中断 | CPU 保存部分现场,跳到中断入口 | 不能依赖用户态栈 |
| 中断分发 | 根据 vector 找 handler | 非法 vector 要安全处理 |
| 快速处理 | 读取设备状态,确认中断来源 | 中断里不能做太慢的事 |
| 缓冲 / 入队 | 把数据放进内核缓冲区或完成队列 | 注意锁和队列容量 |
| 唤醒进程 | 把等待该事件的进程转 ready | 唤醒条件必须精确 |
| 接口 | 职责 | 为什么需要统一 |
|---|---|---|
init(device) | 初始化设备和中断 | 内核启动时能发现并绑定驱动 |
read(request) | 提交读取请求 | 文件系统和终端不用懂硬件细节 |
write(request) | 提交写入请求 | 上层只关心数据,不关心寄存器 |
handle_interrupt() | 处理设备事件 | 中断路径能回到驱动 |
status() | 返回设备状态 | 错误、忙、完成都要可见 |
| 缓冲区 | 解决什么 | 失败风险 |
|---|---|---|
| 键盘输入缓冲 | 中断到达和进程读取速度不一致 | 缓冲满时丢弃、覆盖或阻塞要有规则 |
| 磁盘请求队列 | 多个进程同时提交 IO | 队列无上限会耗尽内存 |
| 网络接收缓冲 | 网卡收包快于应用读取 | 背压、丢包、限额必须明确 |
| 控制台输出缓冲 | 多个进程同时打印 | 输出交错、权限和阻塞策略 |
| 实验 | 通过标准 | 证明了什么 |
|---|---|---|
| 定时器实验 | 固定间隔进入 handler,并触发调度检查 | 中断入口和调度联动成立 |
| 键盘实验 | 按键后阻塞读取进程被唤醒 | 设备事件能转成进程状态变化 |
| 磁盘实验 | read block 提交后阻塞,完成中断后返回数据 | 异步 IO 路径成立 |
| 缓冲区实验 | 输入超过缓冲上限时按规则处理 | 设备不会无限消耗内存 |
| 坏设备实验 | 设备返回错误时,等待进程得到错误码 | 驱动失败不拖垮内核 |