系统中断

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

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

 如前文所述,所有的中断(或异常)都被 统一 的编排在了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指令加一个中断向量向系统发出一个中断请求了,如DOS汇编指令中使用 INT 21 就能调用功能丰富的21号中断服务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值