概述
因为一直依赖都是写的应用,所以对于底层的一些东西有点生疏了,于是乎就需要时不时回来回顾一番,今天我想来聊聊中断。对中断这个东西其实说实话,以前有两个地方我对它印象是比较深的,一个是讲嵌入式系统的时候,里面有各种中断;另外一个就是讲计算机组成的时候,也是各种中断。这两个地方讲的中断可能有一些重叠的地方,但是不全是一样,而这些应该都会在我的回顾里面。
硬中断
首先,还是先来说说什么是中断吧。我们平时在使用计算机的时候,不知道你想过这么一个问题没有,那就是我在键盘/鼠标上按下一个键之后,计算机是怎么知道我已经按下了键盘,并且知道我按下的是哪个键盘的?这其实就是一个典型的涉及到“中断”的问题了,而且这里也隐含了中断的非常重要的概念:上下半部。
那么当我们按下一个按键的时候,在计算机里面发生了什么呢?事实可能是这样的( Linux 系统),当你在键盘按下一个键的时候,键盘会触发出一系列电信号,一般是多个,然后这个电信号随着你的键盘线(或者蓝牙等等)发送给了计算机中的输入模块(DMA),然后 DMA 会发一个信号给 CPU,告诉 CPU 有键盘来信号了。可能在你的理解中,按一个键盘的速度很快,手快的人一秒钟可以按下十几甚至更多的按键,但是,对于计算机来说,这速度太慢了,如果每当 CPU 接收到这个一个信号之后,都去读取你的键盘输入的信号是什么,那么你的计算机可能是无法使用的,当然,除非你的计算时是专门用来打字的另说。
在 Linux 中,现代的内核(2.6 以后)的处理方式一般都是收到有键盘的信号(硬中断)的之后,然后立即将现在忙的进程上下文保存起来,然后看你的硬中断是什么,调用对应的硬中断处理程序,这就是所谓的上半部。上半部一般很短,而且很简单,所以速度很快,一般都是为后面的下半部做准备,例如创建 tasklet 等,然后就完成了任务。在硬中断处理程序中,中断是运行在中断上下文中的,并且同时会屏蔽中断,并且不能在中断处理程序中执行睡眠操作,因为睡眠操作会导致交出 CPU 执行权,从而导致中断上下文错乱,从而导致中断不能得到正确的处理,进而导致等待该中断处理的外设等出错。
硬中断和内核代码的联系是通过 Linux 内核的 IRQ 中断号进行的,而外设等的中断是使用的硬件中断号,而硬件中断号和内核中断号的联系是通过内核头文件的定义关联的。这里所谓的 “硬中断” 就是硬件产生的中断。
总结一下特点就是:
- 硬件中断是一个异步信号, 表明需要注意, 或需要改变在执行一个同步事件.
- 硬件中断是由与系统相连的外设 (比如网卡 硬盘 键盘等) 自动产生的. 每个设备或设备集都有他自己的 IRQ(中断请求), 基于 IRQ, CPU 可以将相应的请求分发到相应的硬件驱动上(注: 硬件驱动通常是内核中的一个子程序, 而不是一个独立的进程). 比如当网卡受到一个数据包的时候, 就会发出一个中断.
- 处理中断的驱动是需要运行在 CPU 上的, 因此, 当中断产生时, CPU 会暂时停止当前程序的程序转而执行中断请求. 一个中断只能中断一颗 CPU(也有一种特殊情况, 就是在大型主机上是有硬件通道的, 它可以在没有主 CPU 的支持下, 同时处理多个中断).
- 硬件中断可以直接中断 CPU. 它会引起内核中相关代码被触发. 对于那些需要花费时间去处理的进程, 中断代码本身也可以被其他的硬件中断中断.
- 对于时钟中断, 内核调度代码会将当前正在运行的代码挂起, 从而让其他代码来运行. 它的存在时为了让调度代码 (或称为调度器) 可以调度多任务.
软中断
和硬中断相对应的就是所谓的软中断了,和硬中断是硬件产生的中断对应,我们可以理解“软中断”是软件产生的中断,但是这里的“软件”意义要更广义一些,“软中断“应该理解为指令产生的中断。这里的所谓的指令不仅仅是主动调用的中断指令,还可能是指令的附加产物,例如获取一个虚拟内存对应的数据,但是这导致了“缺页”,那么“缺页”也是一个 “软中断”。
软中断运行的时候同样有软中断上下文,软中断上下文优先级是高于进程上下文的,所以软中断的执行总是在抢占进程上下文的,这里有一个实际的场景就是在网络收发很频繁的系统中,很可能会因为软中断(Network)过多,从而导致系统进程得不到调度而成为瓶颈的问题,所以这也是一个抢占式 OS 就是银弹的反驳例子。
总结一下特点就是:
- 软中断的处理类似于硬中断. 但是软中断仅仅由当前运行的进程产生.
- 通常软中断是对一些 I/O 的请求.
- 软中断仅与内核相联系, 而内核主要负责对需要运行的任何其他进程进行调度.
- 软中断不会直接中断 CPU, 也只有当前正在运行的代码 (或进程) 才会产生软中断. 软中断是一种需要内核为正在运行的进程去做一些事情 (通常为 I/O) 的请求.
- 有一个特殊的软中断是 Yield 调用, 它的作用是请求内核调度器去查看是否有一些其他的进程可以运行.
硬软中断对比
- 硬件中断是由外设引发的, 软中断是执行中断指令产生的.
- 硬件中断的中断号是由中断控制器提供的, 软中断的中断号由指令直接指出, 无需使用中断控制器.
- 硬件中断是可屏蔽的, 软中断不可屏蔽.
- 硬件中断处理程序要确保它能快速地完成任务, 这样程序执行时才不会等待较长时间, 称为上半部.
- 软中断处理硬中断未完成的工作, 是一种推后执行的机制, 属于下半部.
Linux 系统状态查看
想要了解系统的软中断情况,一个简单的办法就是查看系统文件: /proc/softirqs
,例如下面这个我的例子:
这里各行的信息分别代表:
- HI:最高优先级的软中断类型
- TIMER:Timer 定时器的软中断
- NET_TX: 发送网络数据包的软中断
- NET_RX: 接收网络数据包的软中断
- BLOCK: 快设备的软中断
- TASKLET: 专门为 tasklet 机制准备的软中断
- SCHED:进程调度以及负载均衡
- HRTIMER:高精度定时器
- RCU:专门为 RCU 服务的软中断
如果想了解硬中断的情况,可以查看: /proc/interrupts
系统文件: