中断?异常?有什么区别
在学习的初期,我一直有这么个疑惑:
不都是在IDT中么?不都是通过vector number索引么?中断和异常到底有啥区别呢?
这次我们就来尝试揭开这个谜团。
雷锋和雷峰塔
在想究竟用哪个标题来描述这两者之间的区别,突然想到之前看到过这个就用上了。
当然,实际上这两者的差别并没有这么大。我能想到的两点区别是:
来源不同
处理不同
位置不同
来源不同是指中断是外界引入的。比如键盘,硬盘,网络的数据相应是中断,而异常则是软件执行时自己触发的,比如除0,溢出。 在处理上,异常通常是发送一个信号给到执行的进程,由进程自行决定该如何处理。而中断的处理则由中断函数在处理。 位置不同写的有点模糊,意思是在IDT中,异常和nmi中断的中断向量是固定的,而可屏蔽中断的中断向量是写死的。
来源的不同就不用我来讲了,这是个事实。我就简单说一下后两者。
处理不同
总的来说,中断和异常的处理在内核中是分成两套机制完成的。
异常的处理最后落到给进程发送信号上
中断的处理最后落到do_IRQ函数上
具体的细节将在后续的小节中展开。
对应的中断向量
除此之外,中断和异常在IDT中的位置也是有讲究的。
异常和nmi的中断向量是固定的
可屏蔽中断的中断向量则是可配的
在上一节中,我们看到了中断向量的整个布局。现在我们进一步仔细看看其中哪些是中断哪些是异常。 下面的描述在文件arch/x86/include/asm/irq_vectors.h中。
* Vectors 0 ... 31 : system traps and exceptions - hardcoded events
* Vectors 32 ... 127 : device interrupts
* Vector 128 : legacy int80 syscall interface
* Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 except 204 : device interrupts
* Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts
可以看到其中大部分是中断,而在0-31中保存的是异常的中断向量。那进一步再来看异常向量的布局。
/* Interrupts/Exceptions */
enum {
X86_TRAP_DE = 0, /* 0, Divide-by-zero */
X86_TRAP_DB, /* 1, Debug */
X86_TRAP_NMI, /* 2, Non-maskable Interrupt */
X86_TRAP_BP, /* 3, Breakpoint */
X86_TRAP_OF, /* 4, Overflow */
X86_TRAP_BR, /* 5, Bound Range Exceeded */
X86_TRAP_UD, /* 6, Invalid Opcode */
X86_TRAP_NM, /* 7, Device Not Available */
X86_TRAP_DF, /* 8, Double Fault */
X86_TRAP_OLD_MF, /* 9, Coprocessor Segment Overrun */
X86_TRAP_TS, /* 10, Invalid TSS */
X86_TRAP_NP, /* 11, Segment Not Present */
X86_TRAP_SS, /* 12, Stack Segment Fault */
X86_TRAP_GP, /* 13, General Protection Fault */
X86_TRAP_PF, /* 14, Page Fault */
X86_TRAP_SPURIOUS, /* 15, Spurious Interrupt */
X86_TRAP_MF, /* 16, x87 Floating-Point Exception */
X86_TRAP_AC, /* 17, Alignment Check */
X86_TRAP_MC, /* 18, Machine Check */
X86_TRAP_XF, /* 19, SIMD Floating-Point Exception */
X86_TRAP_IRET = 32, /* 32, IRET Exception */
};
这个表大家也可以对应SDM Volume 3中Table 6-1 Protected-Mode Exceptions and Interrupts一起看。这样也找到了手册和代码之间的一个对应关系。
好了,了解了这两者的区别后,我们就可以来看看内核中是如何处理他们的了。
Last updated
Was this helpful?