中断机制

 中断机制是现代计算机系统中的基本机制之一,他完成了对计算机各个事件(如时钟、键盘等)响应工作。
 首先,中断分为 软中断硬件中断。其中软中断又被称为 异常(exception),他用于处理计算机执行过程中的一些异常情况,如除0操作、溢出、栈错误等情况,这些中断 不可屏蔽。而硬件中断又分为了外部中断(可屏蔽)内部中断(不可屏蔽),外部中断一般就是计算机外设所发出的中断(如敲击了键盘等),它们由如下图所示的两个级联的8259A芯片所控制 ;内部中断就是计算机内部硬件出现的像硬件出错(掉电、校验、传输)等情况所发出的中断。上述所有的这些中断,都被统一的编排在了接下来将介绍的中断向量表中。

中断机制_第1张图片

 8086机器中的 中断向量表在80386机器中被改为了 中断描述符表(interrupt description table,IDT),它存放着用于描述各个中断的表项,每个都由8字节组成,包括了该中断的地址、特权级等信息。这些表项又被称为了 门描述符(Gate Descriptor),“门”的含义是当中断发生时必须先通过这些门,然后才能进入相应的 中断处理程序(Interrupt Service Routine, ISR)
中断机制_第2张图片

 如前文所述,所有的中断(或异常)都被 统一的编排在了IDT中,即这个IDT包含了异常向量和硬件中断向量,而IDT中一共有256个门描述符,每个门描述符描述一个中断(或异常),同时就对应着一个中断(或异常)的处理程序。这256个中断或异常向量的分配如下:

  • 从0~31 的向量对应于异常和非屏蔽中断;
  • 从32~47 的向量(即由I/O 设备引起的中断)分配给屏蔽中断;
  • 剩余的从48~255 的向量用来标识软中断。Linux 只用了其中的一个(即128 或0x80向量)用来实现系统调用(trap)。当用户态下的进程执行一条int 0x80 汇编指令时,CPU 就切换到内核态,并开始执行system_call() 内核函数。

 我们先说异常的处理。在这256个处理程序中,前32个都是非屏蔽中断,0~20号中断处理程序又都用于CPU的异常中断(即软中断),随后的12个中断处理程序被Intel保留,详细情况如下:

// 0~31个都是非屏蔽中断
// 声明中断处理函数 0-19 属于 CPU 的异常中断 
// ISR:中断处理程序(interrupt service routine)
void isr0();        // 0 #DE 除 0 异常 
void isr1();        // 1 #DB 调试异常 
void isr2();        // 2 NMI 
void isr3();        // 3 BP 断点异常 
void isr4();        // 4 #OF 溢出 
void isr5();        // 5 #BR 对数组的引用超出边界 
void isr6();        // 6 #UD 无效或未定义的操作码 
void isr7();        // 7 #NM 设备不可用(无数学协处理器) 
void isr8();        // 8 #DF 双重故障(有错误代码) 
void isr9();        // 9 协处理器跨段操作 
void isr10();       // 10 #TS 无效TSS(有错误代码) 
void isr11();       // 11 #NP 段不存在(有错误代码) 
void isr12();       // 12 #SS 栈错误(有错误代码) 
void isr13();       // 13 #GP 常规保护(有错误代码) 
void isr14();       // 14 #PF 页故障(有错误代码) 
void isr15();       // 15 CPU 保留 
void isr16();       // 16 #MF 浮点处理单元错误 
void isr17();       // 17 #AC 对齐检查 
void isr18();       // 18 #MC 机器检查 
void isr19();       // 19 #XM SIMD(单指令多数据)浮点异常
// 20-31 Intel 保留
//...

 其次再说硬件中断的处理。在前面的8259A芯片的示意图中,可能你已经发现,我们给每一个外部中断(可屏蔽中断)都赋予了一个编号,这16个编号被称作中断请求号码(Interrupt Request, IRQ)。它们实际上就是IDT中的32~47号向量,详细情况如下:

// IRQ 定义
// 定义IRQ
#define  IRQ0     32    // 电脑系统计时器
#define  IRQ1     33    // 键盘
#define  IRQ2     34    // 与 IRQ9 相接,MPU-401 MD 使用
#define  IRQ3     35    // 串口设备
#define  IRQ4     36    // 串口设备
#define  IRQ5     37    // 建议声卡使用
#define  IRQ6     38    // 软驱传输控制使用
#define  IRQ7     39    // 打印机传输控制使用
#define  IRQ8     40    // 即时时钟
#define  IRQ9     41    // 与 IRQ2 相接,可设定给其他硬件
#define  IRQ10    42    // 建议网卡使用
#define  IRQ11    43    // 建议 AGP 显卡使用
#define  IRQ12    44    // 接 PS/2 鼠标,也可设定给其他硬件
#define  IRQ13    45    // 协处理器使用
#define  IRQ14    46    // IDE0 传输控制使用
#define  IRQ15    47    // IDE1 传输控制使用

// 外部中断 
// 声明 IRQ 函数
// IRQ:中断请求(Interrupt Request)
void irq0();        // 电脑系统计时器
void irq1();        // 键盘
void irq2();        // 与 IRQ9 相接,MPU-401 MD 使用
void irq3();        // 串口设备
void irq4();        // 串口设备
void irq5();        // 建议声卡使用
void irq6();        // 软驱传输控制使用
void irq7();        // 打印机传输控制使用
void irq8();        // 即时时钟
void irq9();        // 与 IRQ2 相接,可设定给其他硬件
void irq10();       // 建议网卡使用
void irq11();       // 建议 AGP 显卡使用
void irq12();       // 接 PS/2 鼠标,也可设定给其他硬件
void irq13();       // 协处理器使用
void irq14();       // IDE0 传输控制使用
void irq15();       // IDE1 传输控制使用

 用户程序可通过INT指令加一个中断向量(0~255)像系统发出一个中断请求。

你可能感兴趣的:(中断机制)