中断(interrupt)通常被定义为一个事件,该事件改变处理器执行的指令顺序。这样的事件与cpu芯片内外部硬件电路产生的电信号相对应。
中断通常分为同步(synchronous)中断和异步(asynchronous)中断:
1.同步中断是当指令执行时由cpu控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后cpu才会发出中断。
2.异步中断是由其他硬件设备依照cpu始终信号随机产生的。
intel微处理器中,将同步和异步中断称为异常(exception)和中断(interrupt).
中断是由间隔定时器和i/o设备产生的。异常是由程序的错误产生的。
前一种情况时,内核通过发送一个信号来处理异常。
后一种情况时,内核执行恢复异常需要的所有步骤,如缺页,或对内核服务的一个请求。
中断信号提供一种特殊方式,使得处理器转而去运行正常控制流之外的代码。当一个中断信号达到时,cpu必须停止它当前正在作的事情,并且切换到一个新的活动。为了做到这一点,要在内核态堆栈保存程序计数器的当前值(eip和cs寄存器的内容),并把与中断类型相关的一个地址放进程序计数器。
中断处理与进程切换有一个明显的差异:由中断或异常处理程序执行的代码不是一个进程。它是一个内核控制路径,代表中断发生时正在运行的进程执行。作为一个内核控制路径,中断处理程序比一个进程要轻(light)(中断的上下文很少,建立或终止中断处理需要的时间很少)。
中断处理是由内核执行的最敏感的任务之一,必须满足下列约束:
1.内核的目标是让中断尽可能快的处理完,尽其所能把更多的处理向后推迟。内核响应中断后需要进行的操作分为两部分:关键而紧急的部分,内核立即执行;其余推迟的部分,内核随后执行。
2.中断随时会到来,内核可能正处理其中的一个中断时,另一个中断(不同类型)又发生了。应该尽可能多地允许这种情况发生,因为能维持更多的i/o设备处于忙状态。中断处理程序必须编写使相应的内核控制路经能以嵌套的方式执行,或者,如果中断信号已导致了重新调度,内核能切换到另外的进程。
3.尽管内核在处理前一个中断时可以接受一个新的中断,但在内核代码中还是存在一些临界区,在临界区中,中断必须被禁止。必须尽可能地限制这样的临界区,因为根据以前的要求,内核,尤其是中断处理程序,应该在大部分时间内以开中断的方式运行。
中断和异常的分类:
可屏蔽中断(maskable interrupt):i/o设备发出的所有中断请求(IRQ)都产生可屏蔽中断。可屏蔽中断可以处于两种状态:屏蔽(masked)或非屏蔽的(unmasked);一个屏蔽的中断只要还是屏蔽的,控制单元就忽略它。
非屏蔽中断(nonmaskable interrupt):只有几个危机事件(如硬件故障)才引起非屏蔽中断。非屏蔽中断总是由cpu辨认。
处理器探测异常(processor-detected exception):当cpu执行指令时探测到的一个反常条件所产生的异常。可以进一步分为三组,这取决于cpu控制单元产生异常时保存在内核态堆栈eip寄存器中的数值。
1.故障(fault):通常可以纠正;一旦纠正,程序就可以在不失连贯性的情况下重新开始。保存在eip中的数值是引起故障的指令地址,当异常处理程序终止时,那条指令会被重新执行。只要处理程序能纠正引起异常的反常条件,重新执行同一指令就是必要的。
2.陷阱(trap):在陷阱指令执行后立即报告;内核把控制权返回给程序后就可以继续它的执行而不失连贯性。保存在eip中的数值是一个随后要执行的指令地址。只有当没有必要重新执行已终止的指令时,才触发陷阱。陷阱的主要用途是为了调试程序。在这种情况下,中断信号的作用是通知调试程序的一条特殊指令已被执行(例如到了一个程序内的断点)。一旦用户检查到调试程序所提供的数据,就可能要求被调试程序从下一条指令重新开始。
3.异常中止(abort):发生一个严重的错误;控制单元出了问题,不能在eip寄存器中保存引起异常的指令所在的确切位置。异常中止用于报告严重的错误,如硬件故障或系统表中无效的数值或不一致的数值。由控制单元发送的这个中断信号是紧急信号,用来把控制权切换到相应的异常中止处理程序,这个异常中止处理程序除了强制受影响的进程终止外,没有别的选择。
4.编程异常(programmed exception):在编程者发出请求时发生。是由int或int3指令触发的;当into(检查溢出)和bound(检查地址出界)指令检查的条件不为真时,也引起编程异常。控制单元把编程异常作为陷阱来处理。编程异常通常也叫软中断。这样的异常有两种常用的用途:执行系统调用及给调试程序通报一个特定的事件。
每个中断和异常是由0-255之间的一个数来标识。因为一些未知的原因,intel把这个8位的无符号整数叫作一个向量(vector)。非屏蔽中断的向量和异常的向量是固定的,而可屏蔽中断的向量可以通过对中断控制器的编程来改变。
每个能够发出中断请求的硬件设备控制器都有一条名为irq的输出线。所有现有的irq线都与一个名为可编程中断控制器的硬件电路的输入引脚相连,可编程中断控制器执行下列动作:
1.监视irq线,检查产生的信号。如果有两条以上的irq线上产生信号,就选择引脚编号较小的irq线。
2.如果一个引发信号出现在irq线上:
a.把接收到的引发信号转换成对应的向量。
b.把这个向量存放在中断控制器的一个i/o端口,从而允许cpu通过数据总线读此向量。
c.把引发信号发送到处理器的intr引脚,即产生一个中断。
d.等待,直到cpu通过把这个中断信号写进可编程中断控制器的一个i/端口来确认它;当这种情况发生时,清intr线
3.返回第一步。
irq线是从0开始顺序编号的,因此第一条irq线通常表示成irq0。与irqn关联的intel的缺省向量是n+32.如前所述,通过向中断控制器端口发布合适的指令,就可以修改irq和向量之间的映射。
可以有先择的禁止每条irq线。可以对pic编程从而禁止irq,可以告诉pic停止对给定的irq线发布中断,或者激活它们。禁止的中断是丢失不了的,它们一旦被激活,pic就又把它们发送到cpu。这个特点被大多数中断处理程序使用,因为这允许中断处理程序逐次地处理同一类型的irq.
有选择地激活/禁止irq线不同于可屏蔽中断的全局屏蔽/非屏蔽。当eflags寄存器的if标志被清零时,由pic发布的每个可屏蔽中断都由cpu暂时忽略。cli和sti汇编指令分别清除和设置该标志。
linux 2.6源代码情景分析笔记之中断与异常1
最新推荐文章于 2024-09-06 18:06:22 发布