MIT 6.1810 · Lab traps · 陷阱
本实验探讨如何使用陷阱实现系统调用。你将首先进行栈的热身练习,然后实现用户级陷阱处理。
在开始编码之前,阅读xv6 手册的第 4 章,以及相关源文件:
$ git fetch
$ git checkout traps
$ make clean
你的 xv6 仓库中有一个文件 user/call.c。make fs.img 编译它并生成程序的可读汇编版本 user/call.asm。
在 answers-traps.txt 中回答以下问题:
哪些寄存器包含函数的参数?例如,在 main 调用 printf 时,哪个寄存器保存 13?
在 main 的汇编代码中,对函数 f 的调用在哪里?对 g 的调用在哪里?(提示:编译器可能会内联函数)
函数 printf 位于什么地址?
在 main 中对 printf 的 jalr 之后,寄存器 ra 中的值是什么?
运行以下代码,输出是什么?
unsigned int i = 0x00646c72;
printf("H%x Wo%s", 57616, (char *) &i);
输出取决于 RISC-V 是小端序。如果 RISC-V 是大端序,你会将 i 设置为什么值以产生相同的输出?
在以下代码中,'y=' 之后会打印什么?为什么会发生这种情况?
printf("x=%d y=%d", 3);
在 kernel/printf.c 中实现 backtrace() 函数。在 sys_pause 中插入对此函数的调用,然后运行 bttest。
backtrace:
0x0000000080002cda
0x0000000080002bb6
0x0000000080002898
一些提示:
static inline uint64
r_fp()
{
uint64 x;
asm volatile("mv %0, s0" : "=r" (x) );
return x;
}你将向 xv6 添加一个功能,在使用 CPU 时间时定期提醒进程。添加一个新的 sigalarm(interval, handler) 系统调用。如果应用调用 sigalarm(n, fn),则在程序消耗每个 n 个 CPU "tick" 后,内核应该调用应用函数 fn。
$ alarmtest
test0 start
........alarm!
test0 passed
...
test3 passed
$ usertests -q
...
ALL TESTS PASSED
一些提示:
int sigalarm(int ticks, void (*handler)());
int sigreturn(void);你必须确保当警报处理程序完成后,控制返回到用户程序被定时器中断中断的指令。你必须确保寄存器内容恢复到中断时的值。
一些提示:
创建一个新文件 time.txt,放入一个整数,表示你花在实验上的小时数。
将你的答案写在 answers-traps.txt 中。
运行 make zipball,上传到 Gradescope。