1、 CPU的自动进行的工作:
(a)如果当前是核心态进程在运行(根据TSS判断),则在系统的核心堆栈里保存被中断的核心进程的上下文,直接转向中断处理。如果系统的核心堆栈空间不足,放弃该中断的处理并转入内核错误的中断处理。
(b)如果不是核心态进程,自动切换到TSS所指示的堆栈,在堆栈里依次保存 SS,ESP,EFALGS,CS,EIP。
(c)然后识别中断类型:
(c.1)硬件中断,即CPU中断引脚收到中断请求的信号,CPU发出中断确认信号后,中断控制器把中断状态寄存器中保存的中断号放到总线上,CPU读取总线上的数据。
(c.2)软件中断,指令分析器根据指令的中断号送CPU。
(d)以中断号为索引读取IDT表,EIP变为中断向量的入口函数指针。
2、系统调用入口(在entry.S中system_call:):
直接保存中断号和SAVE_ALL,根据系统调用参数调用相应的处理例程。然后跳到系统调用的出口(在entry.S中ret_from_sys_call)。
3、设备中断入口(使用irq.h的宏BUILD_IRQ(nr)在irq.c中建立):
在orig_eax里保存中断号的相反数(负值),转到common_interrupt入口(使用irq.h的宏BUILD_COMMON_IRQ()在irq.c中建立)进行进程上下文保存(SAVE_ALL),调用do_IRQ(regs),在do_IRQ(...)里,orig_eax会被重新改为正 值作为irq_desc[irq]的访问索引,然后进入中断响应的下面两个嵌套的处理层次。
中断服务例程判断出中断源,将其转换成irq_desc[]数组中偏移值(减去CPU陷入所占的向量个数)。然后调用相应的硬件处理例程irq_desc[irq]->handler->handle
(irq, ®s)。如果此中断的中断硬件处理过程,没有在action链表里找到中断处理例程,则马上返回,不然它将调用对应此中断源的所有irq_action数据结构中的中断处理例程。
当Linux核心调用设备驱动的中断处理过程时此过程必须找出中断产生的原因以及相应的解决办法。为了找到设备驱动的中断原因,设备驱动必须读取发生中断设备上的状态寄存器。设备可能会报告一个错误或者通知请求的处理已经完成。如软盘控制器可能将报告它已经完成软盘读取磁头对某个扇区的正确定位。
一旦确定了中断产生的原因,设备驱动还要完成更多的工作。如果这样Linux核心将推迟这些操作。以避免了CPU在中断模式下花费太多时间。这就是使用Linux提供的bottom half 机制。
4、设备中断出口(在entry.S中ret_from_intr:):
由于Linux的多进程特性,中断处理不一定返回原来被中断的进程(除非它是核心态进程),根据TSS的状态设定进行选择:
(a)被中断进程是用户进程(非超级用户态):重新调度进程(reschedule);
(b)被中断进程是VM86态进程:重新调度进程(reschedule);
(c)被中断进程是核心态进程(超级用户态):直接返回原来进程(RESTORE_ALL)
5、系统调用的出口(在entry.S中ret_from_sys_call):
如果bottom half的队列非空,执行do_bottom_half()函数。然后进入进程调度程序入口ret_with_reschedule:。
6、进程调度程序入口(在entry.S中ret_with_reschedule):
根据TSS的状态设定进行选择:
(a)重新调度进程(reschedule);
(b)信号通讯返回(signal_return);
(c)直接返回原来进程(RESTORE_ALL);