Linux——中断处理

来源:互联网 发布:php idc销售管理系统 编辑:程序博客网 时间:2024/05/29 12:50

       处理器的运行速度与外设的速度不在一个数量级上,为了两者能够相互协同合作,就需要引入中断机制。在外设发通知给处理器后,处理器停下手上的工作,先处理完外设的请求后,再继续进行原先的工作,这就是中断的基本原理。

       现在有支持设备中断当前CPU运行的硬件。CPU的某些引脚与电子线路相连,通过改变电子线路上的电压值就可以暂停CPU当前运行的程序,使它转去执行用于处理中断的特殊程序—中断处理例程。这些引脚中有一个还可以与间隔计时器相连,每隔1/1000秒就能收到一个中断。其它的引脚可以连接到系统中像SCSI控制器等设备上。在把中断信号传送到CPU的一个中断引脚上时,系统经常用中断控制器对设备中断进行分组。这种办法节约了CPU上的中断引脚,也提高了设计系统时的灵活性。中断控制器有控制中断的屏蔽和状态寄存器。设置屏蔽寄存器某一位可以允许或禁止对应的中断,而状态寄存器用于返回系统中当前活跃的中断。
       系统中的某些中断是硬连线实现的,如:实时时钟的间隔定时器是永久连接到中断控制器的第 3脚上的;而其它引脚所连接的中断内容却是由插在某个PCI或ISA插槽上的某种控制卡来决定的。例如中断控制器的引脚4连接到0号PCI插槽上,而0号PCI插槽可能某天插的是以太网网卡,而另一天是SCSI控制器。根本问题是每个硬件系统有自己的中断路由机制,所以操作系统必须要能灵活地处理。
       大多数现代的通用微处理器按相同的方式来处理中断。当发生硬件中断时, CPU会暂停正在执行的指令转移到内存中的某个地址,在这个地址处或者包含中断处理例程、或者是用于转移到中断处理例程的指令。这部分指令通常在CPU的中断模式下执行,一般没有其它的中断可以在这个模式下发生。但对某些处理器仍然有特殊的情况,某些CPU把中断按优先级分类,高级中断可以打断低级的中断。这说明第一级的中断处理代码必须得仔细编写,它经常要有用于存储CPU处理中断前执行状态的栈(CPU的执行状态包括CPU的所有通用寄存器的值和上下文)。某些CPU有一组只在中断模式下才可见的寄存器,中断处理例程可以用这些寄存器去做大多数的上下文(context)保存工作。

     而在软件编程层面,当响应中断时,内核会执行一个称为中断服务例程的函数(ISR)。因此在此之前要先注册中断处理程序,卸载驱动时,还要注销中断处理程序。

中断API

注册中断处理程序

int request_irq(unsigned int irq,                irq_handler_t handler,                unsigned int flags,                const char *name,                void *dev)

       irq:表示分配的终端号。这个值可以通过探测获取,也可以通过编程动态确定。

       handler:函数指针,指向处理这个中断的实际中断处理程序。

       flags:标志位,可以为:IRQF——该标志被设置后,内核在处理此中断程序时,会禁止其他中断,这种用法一般是希望快速执行的轻量级中断;IRQF_SAMPLE_RANDOM——此标志表示这个设备产生的中断对内核熵池有贡献。内核熵池负责提供从各种随机事件导出的真正的随机数,这种情况一般为该中断的产生是不可预知的;IRQF_SHARED——此标志表示在多个中断处理程序之间共享中断线。

       name:为与该中断相关的名称,其为ASCLL文本。

       dev:用于共享中断线,当一个中断处理程序需要释放时,dev将提供唯一的标志信息,以便在共享中断线的诸多中断处理程序中指定具体删除的那个。如果没有共享中断线,只需要把这个位置为NULL就行了。

       request_irq()成功执行后会返回0。返回非0值,就表示有错误发生。同时这个函数可能会睡眠,因此不能在中断上下文或其他不允许阻塞的代码中使用

注销中断处理程序

void free_irq(unsigned int irq,                     void *dev)

      卸载驱动程序时,需要注销相应的中断处理程序,并释放中断线。就通过调用此函数来实现。


参考资料:

      《Linux编程白皮书》、《Linux内核设计与实现》

0 0
原创粉丝点击