中,其作用就是构建一个 irqaction,并设置其handler指向驱动程序提供的handler,挂接到对应的irq_desc上去,在挂接的过程中,需要检查以前的 action是否支持中断共享,如果不支持就不能挂载,否则可以。
* 普通进程可以被中断或异常处理程序打断
* 异常处理程序可以被中断程序打断
* 中断程序只可能被其他的中断程序打断
中断与异常处理
1. 无特权转换。如果CPU的当前执行环境是在内核态,而被中断,我们称之为无特权转换;
2. 特权转换。 如果CPU的当前执行环境是在用户态,而被中断,我们称之为特权转换;这个需要先从用户态的堆栈转换到内核态堆栈中,然后再处理。
中断处理
当执行到common_interrupt的时候肯定已经是在内核态了,
common_interrupt:
addl $-0×80,(%esp) /* Adjust vector into the [-256,-1] range */
SAVE_ALL //保存现场到数据结构pt_regs
movl %esp,%eax //通过eax传递参数pt_regs给函数do_IRQ用
call do_IRQ //关键的中断处理函数,这个并不是我们指明的ISR
jmp ret_from_intr
do_IRQ
进行中断处理,现在我们需要区分两个概念,禁止中断local_irq_disable,禁止抢占内核preempt_disable。
1. 禁止中断,是指设置当前CPU的IF标志位,从而禁止接受中断请求,达到屏蔽中断的目的,在中断处理过程中考虑到多重中断,所以不会禁止中断的。
2. 禁止抢占内核,是指当前进程的运行,不允许被其他进程抢占,因为在中断处理完毕后可能会调用其他进程执行,为了防止这种情况出现,强制在中断处理完毕后必须回到初始中断附属的进程继续执行,也就是说在禁止抢占内核的情况下是允许发生中断的。
中断处理的思想:根据传递过来的中断号,找到irq_desc,调用其中的handle_irq函数,继而调用action中的handler函数 (这个才是真正的ISR),但是同一个中断处理程序之能在某时刻在一个CPU上运行,同时需要注意Linux对于同一个Irq号的中断处理。
do_IRQ ( )
{
…..
Irq_enter( );//上面的都是关闭中断的,由硬件自动关闭中断
Handle_irq()//执行我们定义的中断处理程序ISR,开中断执行,为了中断嵌套
Irq_exit ( );
…..
}
异常处理
因为异常不与外部中断设备打交道,所以其过程比较简单,就是在init_trap中填入到IDT中的中断处理程序,最后调用do_trap进行异常处理,关键也是注意是在用户态还是内核态的问题。异常处理程序在最后向当前进程发送一个信号,因为异常肯定是由当前进程引起的,所以同步于当前进程,由当前进程试图恢复故障(缺页)或者终止。这与中断不一样,中断不于当前进程有