中断分为同步中断和异步中断。在Intel微处理手册中,同步中断称为异常(exception),异步中断称为中断(interrupt)。
同步中断(异常)是当指令执行时由CPU控制单元产生的,它只有在一条指令终止执行后CPU才会发出中断。
异步中断(中断)是由间隔定时器和I/O设备产生的。
中断分为可屏蔽和非屏蔽。
异常分为
1. 故障(fault)
重新执行当前指令,如Page Fault。
2. 陷阱(trap)
执行下一条指令,如Debugger
3. 异常中止(abort)
发生一个严重的错误,强制终止受影响的进程。
4. 编程异常(programmed exception)
由int或int3指令触发。也叫做软中断(software interrupt),有两种常用的用途:执行系统调用和给调试程序通报一个特定的事件。
处理中断时处理器清IF标志,从而关闭将来会发生的可屏蔽中断。而处理异常时,处理器不修改IF标志。
中断和异常处理程序的嵌套执行
中断处理程序必须永不堵塞,也就是中断处理程序运行期间不能发生进程切换。而异常处理程序通常不会发生异常(异常一般由用户态程序引起),而这里有一个特例就是Page Fault异常(由内核引起),然而Page Fault从不进一步引起异常,所以与异常相关的至多有两个内核控制路径(第一个由系统调用引起,第二个由缺页引起)嵌套。
一个中断处理程序既可以抢占其他的中断处理程序,也可以抢占异常处理程序。相反,异常处理程序从不抢占中断处理程序。也就是说中断处理程序从不执行可以导致缺页的操作。
IDT初始化
在内核启用中断之前,IDT的初始地址必须装载到idtr寄存器,并初始化表中的每项。
由于int指令允许用户态进程发出一个中断信号,其值可以是0-255任意一个向量。因此,为了防止用户通过int指令模拟非法的中断和异常,IDT初始化时会把中断或陷阱门的DPL设置成0来实现。然而,在使用系统调用的时候,用户态进程就必须能发出一个编程异常,此时就要把它的DPL设置为3。如int 3。
IDT的两遍初始化,第一遍是在系统启动的时候给BIOS使用的,第二遍是操作系统初始化时Linux自己使用的。
异常处理
Double fault通过任务门来找到正确的上下文信息。
IRQ
中断处理
#ifdef CONFIG_CPU_SH2A
asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
siginfo_t info;
switch (r4) {
case TRAP_DIVZERO_ERROR:
info.si_code = FPE_INTDIV;
break;
case TRAP_DIVOVF_ERROR:
info.si_code = FPE_INTOVF;
break;
}
force_sig_info(SIGFPE, &info, current);
}
#endif