知识全景图/ 软件工程与系统/ 如何设计系统/ 如何设计操作系统/ 设备驱动与中断

如何设计设备驱动与中断

让硬件事件安全进入内核,并把具体设备收成统一接口。

定位:这页不讲完整硬件协议。它只回答 ToyOS 的设备问题:键盘、磁盘、网卡不会按照应用程序的节奏工作,内核必须接中断、托管缓冲区、唤醒等待进程,并把设备差异隐藏在驱动后面。
一、坏场景:硬件不会乖乖等应用轮询
失败:如果应用自己轮询键盘、磁盘和网卡,它会浪费 CPU、绕过权限、和其他程序抢设备,还要懂每种硬件寄存器。设备事件必须先进入内核。
设备事件如果没有中断 / 驱动被迫设计
键盘输入应用一直轮询,CPU 被浪费中断 handler 把字符放入输入缓冲区
磁盘 IO 完成等待进程不知道何时恢复驱动完成请求,唤醒 blocked 进程
网络包到达应用直接碰网卡队列,安全和共享失控内核收包,放入 socket 缓冲区
定时器 tick死循环程序不让出 CPU定时器中断触发调度
二、中断路径最小模型
阶段内核动作注意点
硬件发中断CPU 保存部分现场,跳到中断入口不能依赖用户态栈
中断分发根据 vector 找 handler非法 vector 要安全处理
快速处理读取设备状态,确认中断来源中断里不能做太慢的事
缓冲 / 入队把数据放进内核缓冲区或完成队列注意锁和队列容量
唤醒进程把等待该事件的进程转 ready唤醒条件必须精确
on_interrupt(vector): handler = interrupt_table[vector] if handler == null: return spurious_interrupt() handler() disk_interrupt_handler: req = disk.complete_current_request() req.process.state = ready run_queue.push(req.process)
三、驱动接口只保留最小能力
接口职责为什么需要统一
init(device)初始化设备和中断内核启动时能发现并绑定驱动
read(request)提交读取请求文件系统和终端不用懂硬件细节
write(request)提交写入请求上层只关心数据,不关心寄存器
handle_interrupt()处理设备事件中断路径能回到驱动
status()返回设备状态错误、忙、完成都要可见
四、设备缓冲区是隔离边界
缓冲区解决什么失败风险
键盘输入缓冲中断到达和进程读取速度不一致缓冲满时丢弃、覆盖或阻塞要有规则
磁盘请求队列多个进程同时提交 IO队列无上限会耗尽内存
网络接收缓冲网卡收包快于应用读取背压、丢包、限额必须明确
控制台输出缓冲多个进程同时打印输出交错、权限和阻塞策略
五、验收实验
实验通过标准证明了什么
定时器实验固定间隔进入 handler,并触发调度检查中断入口和调度联动成立
键盘实验按键后阻塞读取进程被唤醒设备事件能转成进程状态变化
磁盘实验read block 提交后阻塞,完成中断后返回数据异步 IO 路径成立
缓冲区实验输入超过缓冲上限时按规则处理设备不会无限消耗内存
坏设备实验设备返回错误时,等待进程得到错误码驱动失败不拖垮内核
六、回到操作系统主线
下一页:IPC 与同步
设备和中断进入内核后,下一步是处理进程之间的等待、唤醒和协作。继续看 如何设计 IPC 与同步
上一步:文件系统
如果你想先看块设备怎样变成文件和目录,回到 如何设计文件系统
回总页
一句话:驱动和中断不是硬件知识堆叠,而是把不可预测的硬件事件收进内核状态机,让设备变成可排队、可限额、可唤醒、可返回错误的资源。