904-中断控制方式
# 904-中断控制方式
那原本为了好好看书好好进行运算,我就不出去吃中饭了, 我定了一份外卖。结果呢?为了能收到这份外卖,我不得不总是去校门口看一看外卖来了 没有。回去看一遍,回来又看一遍,再看一遍,再看一遍。 那结果一上午,啥书都没有看成,对吧。这样就不合算了。 我都还不如玩会儿游戏呢,折腾这个干嘛?
那怎么解决呢?我们得追加投资。啊,增加一个设备, 我们装一部电话。 装一部电话呢,然后跟送外卖的说好,你到了校门口就给我打电话。 那这样呢我就可以安心地坐在这先玩游戏了。 啊,那玩儿,啊,玩的很开心。咦,这个突然电话响了,电话响了。 然后“唉,啊送外卖的, 好好好,这就来, 这就来“,好,这样我们就可以去拿了外卖回来吃完,对吧,什么事都不耽误。 这就是我们今天要说的”中断控制方式“。
# 中断控制方式
在现在的计算机系统当中, 如果完全依靠 CPU 进行输入输出,那是有问题的。 比如说我们要通过键盘进行输入,那 CPU 怎么能保证及时发现键盘的输入呢? 如果 CPU 不间断地去查询键盘的输入, 那显然是不合适的,那这样 CPU 就无法完成其他的任务了。 那如果是间歇地查询呢?先做一段运算的任务,然后查看一下键盘。 那这样也有问题。这个间隔设置为多久合适呢? 间隔设置的太短,那还是影响 CPU 执行其他的任务。 间隔设置的太长,又会造成键盘的输入无法得到及时的响应。
所以想要让这个系统正常的工作,我们还得用其他的方法。 这就是我们要介绍的第二种 I/O 控制方式,中断。 之前我们已经知道了 CPU 是如何处理中断的, 并且分析了内部中断的不同类型。那我们现在要谈的是外部中断。
那我们现在就来了解 CPU 是如何运用中断的方式来进行 I/O 控制的。 我们先来看一个数据输入的过程,还是用这个并行接口电路为例。 那之前在这个结构上我们已经讲解了如何用程序查询方式进行数据的传送。 那想要实现中断控制方式,首先在这个并行接口电路当中,就需要有能够产生中断信号的逻辑电路, 而且要把这个中断请求信号通过主板上的物理连线和 CPU 的中断输入接口连接起来。
然后我们再来看软件操作的过程。那在初始化时, CPU 还是要执行 OUT 指令,将控制字写入到这个接口的控制计存器当中,设置接口的工作模式。 然后 CPU 就可以去执行其他的任务了。
那当外设有数据输入的时候, 就会将数据发到这个并行数据输入信号上,并且把”输入准备好“这个信号置为有效。 而这个接口电路始终在检查”输入准备好“信号是否有效, 一旦发现有效,就从”并行数据输入"信号上接收数据,放入到“输入缓冲寄存器”当中去, 然后将“输入回答”信号置为有效,这是为了告诉外设暂时先不要发送新的数据。
那并行接口的这几步操作和程序查询方式下是一样的。 区别在于这个期间 CPU 不用来反复地读取状态计存器以查询是否有输入的数据。
那在数据已经保存到输入缓冲寄存器当中后,并行接口电路会通过中断控制逻辑将这个中断请求信号置为有效,同时会将状态寄存器当中“输入缓冲满”这个状态位置为有效。 那 CPU 在发现这个中断请求有效后,就进入了中断处理的过程。随后会进入我们专门为并行接口编写的中断服务程序。
那在这段中断服务程序当中,会首先使用 in 指令读入“状态寄存器”当中的状态字, 因为这时 CPU 虽然是收到了中断请求,但它并不清楚是什么原因发生的中断。 所以它需要读出状态字,然后检查其中的各个状态位。 那发现是这个“输入缓冲满”的状态位有效了, 这时才知道是因为有数据的输入发生的中断。 那在这个中断服务程序当中,就会继续执行 in 指令, 从这个“输入缓冲寄存器”当中读出数据。
CPU 可能会对这个读出的数据进入处理,但更多的时候, CPU 会将输入的数据再通过存储器写指令,保存到设置在内存某处的一个缓存区当中。 而在 CPU 将这个输入缓冲寄存器当中的数据读走之后, 并行接口电路就会将输入回答信号置为无效。 这就告诉外设可以继续接收下一个新数据了。
那如果这是一个键盘的接口,可能会过很久才会有一个新数据。 那如果这是一个网络的接口,那可能会连续的有很多新的数据进来。 那刚才介绍的这段过程,就会不断地反复执行。 输入的数据会不断地被 CPU 读走,再写到内存的某个地方。 这样就构成了一大块数据输入的过程。
# 数据输出
然后我们再来看看数据输出的过程。 那刚才说要用中断控制方式,是因为不知道输入什么时候发生。 那输出是由 CPU 控制的,这难道也会不知道什么时候发生吗? 这当然不是。那为什么要用中断控制方式呢? 那我们不妨先来看一看这个过程。
第一步还是设置接口的工作模式。 然后当 CPU 需要输出时,就执行 OUT 指令,将数据写到接口的输出缓冲寄存器当中。 然后接口将这个数据发到“并行数据输出”信号上,并将“输出准备好”置为有效。 那我们要注意的是,大多数对外接口的工作频率都是远远低于 CPU 的工作频率,而且外设很可能会处在没有准备好的状态。所以如果不采用中断的方式,CPU 在这时就不得不反复地读取状态寄存器, 以确定当前的这个数据已经写到外设了,可以发送新的数据, 那这样也就浪费了 CPU 的性能。
所以我们也可以采用中断控制的方式,等到外设已经将这个数据取走之后, 再由并行接口电路将中断请求信号置为有效。 同时将状态寄存器当中的“输出缓冲空”状态位置为有效。
那这时 CPU 可能还在执行别的程序。在收到中断请求后,又进入了并行接口的中断服务程序。 这和刚才数据输入过程发生的中断使用的是同一个中断向量,进入的也是同一个中断服务程序。 这个中断服务程序的一开头,就会去读取状态寄存器, 然后逐个检查其中的个个状态位。那这次发现的是“输出缓冲空”, 所以 CPU 就会将下一个要输出的数据再写到接口的“输出缓冲寄存器”当中去, 从而开始了下一个输出过程。
这样反复地执行刚才介绍的这几个步骤,那我们就可以完成很多数据的输出了。
# 中断控制方式的特点
现在我们来分析一下中断控制方式的特点。 先来看一看优点,有了中断控制方式,CPU 就可以和外设在一定程度上并行的工作,提高了工作的效率, 而且这也让外设有了申请服务的主动权,而不是让程序查询方式那样,CPU 什么时候查到你了,才有可能为你提供服务。 现在外设就可以在有需要服务的时候主动向 CPU 提出请求, 这样在一定程度上,也满足了输入输出处理的实时性要求。
然后我们再来看一看中断控制方式的缺点。 那它最大的缺点就输入输出数据的传送工作任然用 CPU 来承担。 这样就占用了宝贵的 CPU 运算资源,而且在存储器和外设之间进行数据的传送, 这种方式仍然需要将数据先放到 CPU 当中的通用寄存器, 这样通过 CPU 中转一次的传输过程就会显得很冗长,也影响了输入输出的性能。 当然程序查询方式同样也有这些缺点。中断控制方式是节省了其中不断查询状态位的那些工作。 但是中断的机制也引入了一些新的开销。比如要进入和退出中断服务程序, 就需要执行额外的一些指令,这些指令和数据传送本身是没有关系的。 而且在现在复杂的操作系统当中,这样额外指令的数目可能还是非常多的。
那这样是不是说,中断方式就比程序查询方式要好呢? 倒也未必。中断方式确实提高了整个系统运行的效率。 但是对于一些特别重要的事情,查询方式反而能提高响应的速度。 比如说你现在要等的不是快递,而是你的女朋友。 那你就应该一早就到校门口去候着呀,唉一直在看, 来了没,来了没,对吧。那么这样第一时间到的时候,你就能接下来了。 可你现在非要想着怎么提高系统的整体效率, 就跟人家说,唉你到了之后就给我打电话,啊,我接了电话就去找你。 然后呢?你就呆在房间里啊, 玩游戏。玩得很高兴,玩儿,玩儿,玩儿,唉,一会儿电话响了,你还不接。 为什么呢,还得先存盘呢,对吧。保存现场,啊。 把菜单调出来,存,存,存,啊,存好了。存好了再准备 接电话。结果电话不响了,人家生气了,走了。 是啊,你倒是提高了整体系统运行的效率, 以后能给你打电话的也只有快递员了。