"练习6-杨添宝1:中断向量表初始化和中断处理编程"
在计算机体系结构中,中断是处理器响应外部或内部事件的一种机制。中断向量表(Interrupt Vector Table, IVT)是处理器查找中断处理程序的位置的关键数据结构。本练习涉及对中断向量表的初始化以及中断处理函数的编写。
(1)中断向量表中一个表项占32个字节,即两个16字节的双字。每个表项包含两个部分:一个16字节的门描述符,用于指示中断处理程序的地址和一些属性,以及另一个16字节的陷阱门描述符,通常用于系统调用。在x86架构中,中断处理代码的入口通常存储在门描述符的低16位(gd_off_15_0)中,表示中断处理程序的线性地址的低16位。高16位地址存储在段选择子(gd_ss)中,通过段选择子和低16位偏移地址结合,可以确定完整的32位物理地址。
(2)在`kern/trap/trap.c`中,`idt_init`函数负责初始化中断向量表。这个函数应该遍历所有的中断向量,对每个中断向量使用`SETGATE`宏来设置门描述符。`SETGATE`宏在`kern/mm/mmu.h`中定义,它允许我们设定中断处理程序的地址、类型、特权级别等信息。对于除系统调用中断(T_SYSCALL)之外的所有中断,应使用中断门描述符,设置`gd_type`为`STS_IG32`,并且`gd_dpl`设置为0,表示内核态权限。系统调用中断则应使用陷阱门描述符,设置`gd_type`为`STS_TG32`,`gd_dpl`通常设置为3,表示用户态权限。中断处理程序的入口地址可以通过`vectors`数组获取,该数组在`trap.c`中声明并由`tools/vectors.c`生成。
(3)在`trap.c`中的`trap`函数中,我们需要添加处理时钟中断的代码。时钟中断通常用于调度任务和计时。当接收到100次时钟中断时,调用`print_ticks`函数输出“100ticks”。这可以通过增加一个全局变量来记录时钟中断次数,并在每次处理时钟中断时检查这个计数器。如果达到100,就调用`print_ticks`,然后清零计数器。确保这个处理过程不会阻塞其他中断的发生。
完成以上编程任务后,运行系统将每隔大约1秒(取决于时钟中断的频率)输出一次“100ticks”,同时,用户输入的按键也会正常显示在屏幕上。这验证了中断处理和时钟中断处理功能的正确实现。
通过这个练习,我们可以深入理解中断向量表的结构,如何初始化中断向量,以及如何编写中断处理程序,特别是对时钟中断的处理,这些都是操作系统核心功能的重要组成部分。