- 轮询与中断
外部设备与中央处理器交互一般有两种手段:轮询和中断。
(1)轮询(Polling)
很多I/O设备都有一个状态寄存器,用于描述设备当前的工作状态,每当设备状态发生改变时,设备将修改相应状态寄存器位。通过不断查询设备的状态寄存器,CPU就可以了解设备的状态,从而进行必要的I/O操作。为了节约CPU资源,查询工作往往不是连续的,而是定时进行。
轮询方式具有简单、易实现、易控制等优势,在很多小型系统中有大量应用。对那些实时敏感性不高、具有大量CPU资源的系统来说,轮询方式有很广泛的应用。最典型的用途就是在那些任务比较单一的单片机上,嵌入式系统中也有应用。
轮询的一种典型的实现可能是这样的:while(TRUE){/…/ select(,,timeout); /…/};当然这里的select()也可以使用poll()替换。
轮询方式主要存在以下不足:
<1>增加系统开销。无论是任务轮询还是定时器轮询都需要消耗对应的系统资源。
<2>无法及时感知设备状态变化。在轮询间隔内的设备状态变化只有在下次轮询时才能被发现,这将无法满足对实时性敏感的应用场合。
<3>浪费CPU资源。无论设备是否发生状态改变,轮询总在进行。在实际情况中,大多数设备的状态改变通常不会那么频繁,轮询空转将白白浪费CPU时间片。
(2)中断(Interrupt)
中断,顾名思义,就是打断正在进行中的工作。中断不需要处理器轮询设备的状态,设备在自己发生状态改变时将主动发送一个信号给处理器(PIC),后者在接收到这一通知信号时,会挂起当前正在执行的任务转而去处理响应外设的中断请求。中断通知机制通过硬件信号异步唤起处理器的注意,解决了外部设备与处理器之间速度不匹配导致的资源浪费问题。
现代设备绝大多数采用中断的方式与处理器进行沟通,因此设备驱动程序必须能够支持设备的中断特性。处理器在中断到达时会根据不同的中断号找到对应设备(IRR),并对中断请求进行响应处理。中断处理例程ISR(Interrupt Service Routine)由设备驱动程序提供,并在设备驱动模块初始化时注册到系统中断向量表中。从设备发出中断信号,到处理器最终调用ISR进行处理,期间会经过很多步骤,这个过程构成了中断处理框架。中断处理框架包括了进入ISR之前的很多进入路径(entry path),例如MIPS下要经历这样几个步骤:设置或屏蔽相关寄存器;进入异常入口点取指;现场保护;异常分类(MIPS下中断也是一种异常)处理;查找中断向量表路由ISR。不同的操作系统对中断处理框架的设计不尽相同,但是要达到的目的是一样的,那就是最终调用用户注册的设备ISR。
(3)中断与轮询的折衷
虽然轮询方式存在空转损耗导致名声不佳,但并非一无是处。中断模型也并非十全十美,其高优先级的VIP待遇和快速响应要求在极端条件下将造成“活锁”效应。有时候需要发挥粗暴中断和温和轮询各自的优势,根据实际应用情景,在两种模式之间切换。手机导航杆卡死情形的处理是个很好的案例。
在过去的一些手机和PDA设备上安装有导航杆,它支持3种动作(顺时针旋转、逆时针旋转和按键),可方便菜单导航。导航杆的三种动作都会向处理器发出中断。系统中通用的目的I/O(GPIO)端口和导航杆连接。中断处理函数的工作就是查看GPIO数据寄存器解析出导航杆运动。假定导航杆由于存在运动部件(如旋轮偶尔被卡住)引起的固有的硬件问题,从而在GPIO端口产生不同于方波的波形。被卡住的旋轮会不停地产生假的中断,并可能使系统冻结。为了解决这个问题,可以捕获波形分析,在卡住的情况下动态地从中断模式切换到轮询模式。如果旋轮恢复正常,再动态地从轮询模式切换到中断模式,软件也恢复正常模式。
在本文的最后,将介绍Linux网络设备驱动模型中的NAPI机制 ,它采用“中断+轮询”的处理方式代替纯中断处理方式,是中断和轮询的完美合体。 - 中断向量表
中断向量表其实是处理器内部的概念,因为处理器除了会被外部设备中断外,其内部也可能产生异常等事件,例如在MIPS中,中断只是异常的一种。当这些事件发生时,CPU必须暂停手头上的工作,转而去处理中断或异常,因此处理器需要知道到哪里去获得这些中断或异常的处理函数的目标地址。中断向量表就是用来解决这个问题,其中每一项都是一个中断或异常处理函数的入口地址,具体来说4个字节的函数指针将指向一段汇编微码(intConnectCode)执行跳转。
外部设备的中断常常对应向量表中的某一项,这是通用框架的外部中断处理函数入口,因此在进入通用的中断处理函数之后,系统必须知道正在处理的中断是哪一个设备产生的,而这正是由软件中断号irq定的决。中断向量表的内容是由操作系统在初始化阶段来填写,对于外部中断,操作系统负责实现一个通用的外部中断处理函数,然后把这个函数的入口地址放到中断向量表中的对应位置。用户注册设备驱动ISR,实际上就是挂接到中断向量表中,覆盖某一项的默认处理实现特化。
本质上是轮询,中断信号触发中断请求,cpu查询到中断请求之后根据当前中断寄存器配置决定是否进行中断响应。
但是一般情况下的轮询是程序设定固定周期让cpu进行状态查询,是由指令控制的,没记错的话好像某本unix书里称轮询为软中断。
就连中断都是轮询---当有设备事件产生以后,设置CPU的中断引脚触发中断,而CPU在每个时钟周期都查询是否有中断发生,在有中断时就转到中断处理程序去执行.这是典型的轮询...
最近在看Linux内核,看到中断和异常这块,想起来了以前体系结构课上讲到的关于轮询和中断的概念。二者都是操作系统和硬件交互的方式。开始时是轮询的方法,内核(通常是驱动)需要自己去轮询硬件看硬件是否有事件,如果有则处理,没有则继续轮询,直到被操作系统挂起。这显然是很低效的。于是有了中断这种更好的方案。
但我认为中断本质上仍然是轮询,只不过是把轮询操作放在了硬件层,提高了轮询的效率。中断是如何实现的?通过IRQ(Interrup ReQuest),IRQ其实就是一个硬件的轮询系统,它连接了所有的硬件,每个硬件分配一个独立的IRQ编号。硬件有消息就会放在它自己的IRQ里。然后CPU会在每个指令周期结束时查看IRQ里是否有消息,如果有就触发中断给内核去处理。
作者:Michaelbest1
链接:https://www.jianshu.com/p/cb6df317b16a
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
总结一下就是:当主体需要了解客体的状态,而主体并不能直接接收到客体的消息时,主体的轮询是无法避免的。主体所能做的是尽可能把轮询的操作放在更底层,这样才可以提高效率。
1.对中断进行图示解释
、
2.对轮询进行图示解释