Lab 3 - Exercise 4
Exercise 4
修改 trapentry.S 和 trap.c 并实现Lab 3 中的功能。
trapentry.S 中的宏 TRAPHANDLER 和 TRAPHANDLER_NOEC 和 inc/trap.h 中的 T_* 定义可以帮助我们
我们需要使用那两个宏每个为每个 定义在 inc/trap.h 中的 trap 添加一个 entry point (trapentry.S),同时我们需要提供 _alltraps 供宏TRAPHANDLER 引用
我们还需要修改trap_init()来初始化 idt,使其指向trapentry.S中定义的每个entry point;在这里,宏SETGATE可以帮助我们。
我们的 _alltraps 应该按以下步骤执行:
- push values to make the stack look like a struct Trapframe
- load GD_KD into %ds and %es
- pushl %esp to pass a pointer to the Trapframe as an argument to trap()
push esp 入栈使得 Trapframe 指针可以作为参数传递给 trap() - call trap (can trap ever return?)
考虑使用 the pushal instruction ;它很适合结构Trapframe的布局。
在进行任何系统调用之前,使用用户目录中的一些会导致异常的测试程序(例如user/divzero)测试陷阱处理代码。使用make grade 命令 测试,应该可以通过 divzero, softint, and badsegment 这几个测试
先理解几个文件的作用和关系
trap:可以理解为中断或异常
- inc/
trap.h——>Public definitions for trap handling - kern/
trap.h——>Kernel-private trap handling definitions
trap.c——>Trap handling code,包含idt的初始化
trapentry.S——>Assembly-language trap handler entry-points(入口点)
异常处理具体流程:
cpu在每条指令执行的最后一个时钟周期检测中断请求,如果有中断信号,cpu自动进入中断响应周期。(具体请看微机原理8086中断系统和中断控制器)
cpu检测到中断后,会做以下事情:
- 处理器切换到由TSS的SS0和ESP0字段定义的堆栈,SS0和ESP0的对应的值分别是GD_KD和KSTACKTOP。
- 处理器从KSTACKTOP地址开始,将异常参数压入内核栈:
- 因为我们正在处理一个除法错误,它是x86上的中断向量0,处理器读取IDT条目0并设置CS:EIP指向该条目所描述的处理函数。(通过IDT找到trapentry.S,再通过trapentry.S找到trap.c)
![image]()
- handler函数接管并处理异常,例如通过终止用户环境。
handler 存于 trapentry.S 当中
IDT 中保存着 handler 的地址,这一步的初始化是由 kern/trap.c 中的 trap_init() 做的
处理器通过IDT找到在 kern/trapentry.S 中的 hanlder。
handler 调用 kern/trap.c 中的 trap() ,同时传入一个 Trapframe 结构的参数(这个参数用于保存寄存器状态,结构位于 inc/trap.h)。
然后 trap() 处理异常/中断或分派给一个特定的处理函数。
exercise 4 的作业是补充 trapentry.S 和 trap.c。
inc/trap.h 中定义了各种各样的 Trap numbers,我们需要在 trapentry.S 中 添加与这些 Trap numbers 对应的 trap 的入口。
题目也讲了,宏TRAPHANDLER和TRAPHANDLER_NOEC 可以帮助我们创建这些入口。
宏TRAPHANDLER作用就是在调用者的代码中 创建一个名字为name方法的函数。name方法的函数作用就是将trap num 入栈,然后跳转_alltraps函数。
宏TRAPHANDLER_NOEC作用就是创建一个名字为name方法的函数,name方法的函数作用就是直接跳转_alltraps函数




浙公网安备 33010602011771号