中断发生时Linux首先读取系统可编程中断控制器中中断状态寄存器判断出中断源,将其转换成irq_action数组中偏移值。例如中断控制器引脚6来自软盘控制器的中断将被转换成对应于中断处理过程数组中的第7个指针。如果此中断没有对应的中断处理过程则Linux核心将记录这个错误,不然它将调用对应此中断源的所有irqaction数据结构中的中断处理例程。
当Linux核心调用设备驱动的中断处理过程时此过程必须找出中断产生的原因以及相应的解决办法。为了找到设备驱动的中断原因,设备驱动必须读取发生中断设备上的状态寄存器。设备可能会报告一个错误或者通知请求的处理已经完成。如软盘控制器可能将报告它已经完成软盘读取磁头对某个扇区的正确定位。一旦确定了中断产生的原因,设备驱动还要完成更多的工作。如果这样Linux核心将推迟这些操作。以避免了CPU在中断模式下花费太多时间。在设备驱动中断中我们将作详细讨论。
File translated from TEX by TTH, version 1.0.
Top of Chapter, Table of Contents, Show Frames, No Frames � 1996-1999 David A Rusling copyright notice. 本章主要描叙Linux核心的中断处理过程。尽管核心提供通用机制与接口来进行中断处理,大多数中断处理细节都是CPU体系结构相关的。 图7.1 中断路由的逻辑图Linux通过使用多种不同硬件来执行许多不同任务。包括驱动显示器的视频设备、驱动硬盘的IDE设备等。 我们可以同步驱动这些设备,即我们可以发送一个请求执行一组操作(比如说将一块内存数据写入到磁盘)然后等待到执行完毕。这种方式虽然可以工作,但是效率很低,因为操作系统必须等待每个操作的完成,所以操作系统将花费大量时间在“忙等待”上。更为有效的方式是执行请求,然后转去执行其它任务。当设备完成请求时再通过中断通知操作系统。这样系统中可以同时存在多个未完成的任务。
不管CPU在作什么工作,为了让设备产生中断必须提供一些必要的硬件支持。几乎所有的通用处理器如 Alpha AXP都使用近似的方法。CPU的一些物理引脚被设计成可以改变电压(如从+5V变成-5V)从而引起CPU停止当前工作并开始执行处理中断的特殊代码:中断处理程序。这些引脚之一被连接到一个周期性时钟上并每隔千分之一秒就接收一次中断,其它引脚则可连接到系统中其它设备如SCSI控制器上。
系统常使用中断控制器来在向CPU中断引脚发送信号之前将设备中断进行分组。这样可以节省CPU上中断引脚个数,同时增加了系统设计的灵活性。此中断控制器通过屏蔽与状态寄存器来控制中断。通过设置屏蔽寄存器中的某些位可以使能或者关闭中断,读取状态寄存器可得到系统当前处于活动状态的中断。
系统中有些中断是通过硬连线连接的,如实时时钟的周期性定时器可能被固定连接到中断控制器的引脚3上。而其它连接到控制器的引脚只能由插到特定ISA或PCI槽中的控制卡来决定。例如中断控制器中的引脚4可能被连接到PCI槽号0,但可能某天此槽中插入一块以太网卡而过几天又会换成SCSI控制器。总之每个系统都有其自身的中断路由机制,同时操作系统还应该能灵活处理这些情况。
多数现代通用微处理器使用近似的方法来处理中断。硬件中断发生时,CPU将停止执行当前指令并将跳转到内存中包含中断处理代码或中断处理代码指令分支的位置继续执行。这些代码在一种特殊CPU模式: 中断模式下执行。通常在此模式下不会有其它中断发生。但是也有例外;有些CPU将中断的优先级进行分类,此时更高优先级的中断还可能发生。这样意味着必须认真编写第一级中断处理代码,同时中断处理过程应该拥有其自身的堆栈,以便存储转到中断处理过程前的CPU执行状态(所有CPU的普通寄存器和上下文)。一些CPU具有一组特殊的寄存器-它们仅存在于中断模式中,在中断模式下可以使用这些寄存器来保存执行所需要的执行上下文。
当中断处理完毕后CPU状态将被重储,同时中断也将被释放。CPU将继续做那些中断发生前要做的工作。中断处理代码越精炼越好,这样将减少操作系统阻塞在中断上的时间与频率。
7.1 可编程中断控制器