说明
- @author blog.jellyfishmix.com / JellyfishMIX - github
- LICENSE GPL-2.0
中断
首先不考虑硬中断软中断的概念,只理解中断的概念:
中断是 cpu 用来响应硬件设备请求的一种机制,硬件设备设置中断标志,cpu 检测到中断标志时,会挂起正在执行的线程,然后调用内核的中断处理程序来处理。
中断的缺点:
- cpu 当前执行的中断处理程序没有执行完之前,其他的中断标志都无法被响应。即执行当前中断期间,其他后提交的中断可能会丢失。
- cpu 感知到中断后要立刻处理,会强制占用 cpu 时间片,且中断占用的 cpu 时间片分配未经操作系统的线程调度。
改进中断的缺陷–中断拆分为硬中断 + 软中断
参考 linux 硬中断软中断的思路,为了避免中断丢失和中断可能占用 cpu 时间过长且未经操作系统调度的问题,把一次完整的中断拆为(硬中断 + 软中断)两部分执行。我们以网络 IO 的硬中断软中断举例。
硬中断
linux 的硬中断准备上下文(比如从网卡缓冲拷贝到 sk_buffer 内存中)并提交软中断任务。
软中断
软中断任务(比如解析 TCP 协议判断目标 Socket,把 sk_buffer 关联至对应 Socket,唤醒 Socket 上等待的进程等)在专门的 ksoftirqd 线程中执行。ksoftirqd 线程就在 while 循环中不断地执行软中断任务。
ksoftirqd 线程每个 cpu 一个。
题外话-中断的过程
中断的过程可参考: link
中断的触发
触发中断的,实质上既不是外部设备,也不是标志,而是 cpu 自己。cpu 在每个指令周期的开头瞅一眼中断标志,有,则进入处理过程,没有,则继续做它自己的事。如果不巧,标志置晚了,cpu 已经检查完了标志,那只能等下一轮指令周期再检查。
因此晶振是中断的基石,晶振产生固定的频率,cpu 每个指令周期需要建立在固定频率基础上。
中断优先级
cpu 检测到不止一个中断标志是完全可能的,而它一次只能选择一个来处理。一般会按照一定规则挑出优先级最高的一个标志,剩下的先放着,等下个指令周期再检测。
cpu 开始处理一个中断时,被处理的这个标志会怎么样
当 cpu 开始处理一个中断的时候,被处理的这个标志会怎么样,根据中断的具体类型不同,标志可能被 cpu 自动清除掉,也可能不会,而是等驱动程序来手动清除。
中断丢失–cpu 开始处理一个中断时,其他尚未被处理的标志会怎么样
如果一个标志还没被处理,就有硬件要设置一个同样的标志(重点是: 同样的),前一个标志会丢失。设置标志的场地只有一个,只能记录标志有没有,不能记录标志有几个。这就是中断丢失。
题外话-硬件 buffer
鼠标键盘每点击一次就要触发一次 cpu 中断,不过相比硬盘和网卡的 IO,鼠标键盘算低俗 IO 了,一秒点不了几次,中断一下问题不大。
网卡和硬盘 IO 太快,为了避免总是中断 cpu,所以搞了 buffer。例如硬盘通过 DMA 控制器先往 buffer 里写好了再触发 cpu 中断去 buffer 里读。
扩展阅读
推荐一篇很好的文章,了解 linux IO 全过程。本文受此文章介绍的启发。如果想了解操作系统的 IO,不容错过。《从内核角度看IO模型》