中断与任务协作 — 专题笔记
← 操作系统知识地图 | ← CPU运行模式与特权指令 | ← 调度算法与上下文切换
中断分类
中断按信号来源分两类:
| 外中断 | 内中断(异常) | |
|---|---|---|
| 信号来自 | CPU 外部(外设) | CPU 内部 |
| 和当前指令关系 | 异步,无关 | 同步,当前指令直接导致 |
| 例子 | 时钟中断、网卡收包、按键 | 缺页、除零、非法指令 |
| 可否屏蔽 | 可屏蔽中断可以关 | 大部分不可屏蔽 |
教材里常考三种具体的中断类型,正好对应态切换的三条路:
| 中断类型 | 对应场景 | 谁触发 | 主动/被动 |
|---|---|---|---|
| 访管中断 | 系统调用 | 用户程序 | 主动 |
| 时钟中断 | 硬件中断 | 外设(定时器) | 被动 |
| 缺页中断 | 异常 | CPU 自身 | 被动 |
三条路的硬件流程完全一样:保存现场 → 切内核态 → 跳处理程序 → 恢复现场 → 回用户态。区别只在于谁发了这个”敲门”信号。
访管中断(系统调用)
“访管”就是访问管理程序(操作系统内核)。用户程序执行陷入指令(syscall / int 0x80),CPU 切到内核态,OS 根据系统调用号查表,执行对应服务(读文件、分配内存、创建进程),完事再切回来。整个过程是主动的——用户程序知道自己需要 OS 帮忙,自己发起。
时钟中断
CPU 里有一个硬件定时器,到时间了就向 CPU 发中断信号。这是外中断——异步到达,和当前指令无关。
时钟中断是操作系统调度器的命根子。没有它,一个程序占了 CPU 就不会主动让出来,其他程序全饿死。内核拿到时钟中断后做两件事:更新系统时间、检查当前进程的时间片用完没,用完了就换下一个进程。
FreeRTOS 的
xPortSysTickHandler就是时钟中断的 ISR,滴答一下,任务调度就有可能发生。
缺页中断
CPU 执行指令时发现要访问的虚拟地址没有对应的物理页框(页表项里”存在位” = 0),当场触发缺页中断。这是异常(内中断)——指令执行过程中 CPU 自己发现的,同步于当前指令。
缺页中断的特别之处在于:它不是”出错就杀掉进程”。OS 会判断地址是否合法,合法就从磁盘把缺的那页换进内存,然后重新执行刚才那条指令——这次页表里有了,顺利跑过去。详见 虚拟内存。
中断检查时机
CPU 一般不是在一条指令执行到一半时响应中断,而是在每条指令执行结束的最后时刻做一次中断扫描。
可以直接记成:
- 先执行完当前指令。
- 再扫描中断请求寄存器、屏蔽寄存器和优先级相关状态。
- 若存在可响应中断,再转入
ISR。
中断响应流程
- 执行完当前指令。
- 保存断点和必要现场。
- 查中断向量表,跳到对应
ISR。 ISR处理完成后恢复现场。- 返回原程序,或先触发调度。
中断与任务怎么协作
中断负责快处理,任务负责重处理。
ISR里只做读状态、清标志、取走最小必要数据、通知任务。- 复杂计算、协议解析、打印日志、阻塞等待等工作放到任务里做。
常见链路是:
- 外设发出中断请求。
- CPU 在当前指令结束后响应中断。
ISR快速处理并唤醒任务。- 任务在正常上下文中完成后续工作。
为什么不能在中断里做重活
- 会拖慢系统响应。
- 会阻塞后续中断。
- 会推迟调度。
- 很多接口本来就不能在中断上下文中调用。