如果用一句话概括操作系统的原理,那就是:整个操作系统就是一个中断驱动的死循环,用最简单的代码解释如下:
while(true){
doNothing();
}
其他所有事情都是由操作系统提前注册的中断机制和其对应的中断处理函数完成的。我们点击一下鼠标,敲击一下键盘,执行一个程序,都是用中断的方式来通知操作系统帮我们处理这些事件,当没有任何需要操作系统处理的事件时,它就乖乖地待在死循环里不出来。
所以,中断非常重要,它是让我们理解整个操作系统的根基。
五花八门的中断分类
在Intel CPU手册中对中断的定义有一个官方的标准答案。如下图:
这段话概括起来的意思就是:中断可以分为中断和异常,异常又可以分为故障、陷阱和中止。
第一句话有点奇怪,啥叫中断又可以分为中断和异常呢?其他很多文章也是这么写的,不知道你有没有感到疑惑。
原文的意思准确的说就是,CPU提供了两种中断程序执行的机制,中断和异常。第一个中断是动词,第二个中断时真正的机制种类。
先说第一个机制---中断(interrupt),中断时一个异步事件,通常由I/O设备触发。比如点击一下鼠标,敲击一下键盘。
再说第二个机制--异常,异常是一个同步事件,是CPU在执行指令时检测到的反常条件。比如除法异常、错误指令异常、缺页异常等。
这两个机制,殊途同归,都是让CPU收到一个中断号,至于CPU收到这个中断号后干什么,我们暂且不管。
我们先看看收到中断号之前,中断和异常是怎么给CPU一个中断号的。先说中断。
有一个设备叫做可编程中断控制器,它有很多IRQ引脚线,接入了一堆能发出中断请求的硬件设备。当这些硬件设备给IRQ引脚发送一个信号时,由于可编程中断控制器提前被设置好了IRQ与中断号的对应关系,所以就转化成了对应的中断信号。把这个中断号存储在自己的一个端口上,然后给CPU的INTR引脚发送一个信号,CPU收到INTR引脚信号后,去刚刚的那个端口可读取到这个终端号的值。
你看,最终的目标,就是让CPU知道,有中断了,并且也知道中断号时多少。
比如按下图3中的键盘,最终到CPU那里的反应就是,得到了一个中断号0x21。
那异常的即使就更简单了,时CPU自己执行指令时检测到一些反常情况,然后自己给自己一个中断号,无须外界提供。
比如,CPU执行到了一个无效指令,则自己给自己一个中断号0x06,这个中断号是CPU提前就规定好写死了的硬布线逻辑。
好了,到目前位置,我们知道了无论是中断还是异常