CPU判断当前CPL级别如果等于3,则导致堆栈切换3->0,堆栈切换过程: a. CPU从当前TR指向的TSS中读取SS0和ESP0; b. CPU将当前的【SS:ESP】寄存器内容临时保存起来,假设为SSt和ESPt; c. CPU将SS0和ESP0恢复到【SS:ESP】寄存器中; d. CPU将在b中临时保存的SSt和ESPt压入当前的堆栈【SS:ESP】中(其实就是SS0和ESP0);
2. 来到do_IRQ: a. 首先给硬中断计数加1,irq_enter(cpu, irq)也就是:++local_irq_count(cpu);每进入一个硬中断处理函数前,local_irq_count(cpu)计数便被加1,处理完毕后减1; b. 如果当前设备中断处理函数可以在中断打开的情况下运行,则调用sti将EFLAGS.IF置位,打开硬中断使能; c. 调用request_irq注册的设备硬中断处理函数; d. 无论EFLAGS.IF是否为0,都调用cli将EFLAGS.IF清零,将硬中断使能关闭; e. 给硬中断计数减1,irq_enter(cpu, irq);该函数其实就是:--local_irq_count(cpu); f. 如果此时有软中断需要运行(如在前面的硬中断处理函数中调用__cpu_raise_softirq),则进入do_softirq中处理软中断,关于do_softirq中的处理步骤见3; e. do_IRQ执行ret,返回到ret_from_intr。
3. do_softirq: a. 首先判断当前是否还有没有处理完毕的硬中断处理程序或软中断处理程序,如果有,则直接退出该函数。判断方法见附注【文(6)】。 b.将软中断处理计数加1,local_bh_disable()也就是local_bh_count(cpu)++;每进入do_softirq准备进行处理软中断前,local_bh_count(cpu)计数便被加1,软中断处理函数处理完毕后,在do_softirq返回前,将其值减1; c. 无论EFLAGS.IF是否为0,都调用cli将EFLAGS.IF清零,将硬中断使能关闭,处理些软中断标志位的问题,随后调用sti将EFLAGS.IF置位,打开硬中断使能; d. 执行软中断处理函数; e. 调用cli将EFLAGS.IF清零,将硬中断使能关闭,处理些软中断标志位的问题; f. 将软中断处理计数减1,local_bh_enable()也就是local_bh_count(cpu)--; g. 返回到2.e中;