6.S081 lab4 traps
#Backtrace
-
在
kernel/riscv.h中添加hints所给的r_fp函数,这个函数的作用是取出s0寄存器的值,该寄存器保存了当前的帧指针。栈帧的布局图如下:
可以看出返回地址和前一个栈帧的帧指针的保存位置是固定的,分别为
fp-8和fp-16。 -
弄懂这个图就很容易写出代码了,首先调用
r_fp读取当前的帧指针,通过PGROUNDUP对其页面上取整,这里对页面上取整的原因是:可能一个物理页中有多个栈帧嵌套,我们需要打印出所有的返回地址。代码如下:void backtrace(void) { printf("backtrace:\n"); // 读取当前帧指针 uint64 fp = r_fp(); uint64 base = PGROUNDUP(fp); while (fp < base){ uint64 ret_adr = *(uint64*)(fp - 8); printf("%p\n", ret_adr); // 前一个帧指针 fp = *(uint64*)(fp - 16); } }
#Alarm
做这个实验之前,一定要弄清楚
xv6处理trap的过程,建议好好看一下xv6 book的第四章
-
加入系统调用原型等操作不再赘述。在
struct proc中加入以下字段。alarm_interval:报警间隔alarm_handler:指向处理函数的指针ticks_count:距离上一次定时器中断所经历的ticksalarm_trapframe:发生定时器中断时,进程的trapframe,用来恢复进程的执行flag:标记上一次的报警处理程序是否已经执行完,0表示已处理完报警。

-
更改
usertrap以处理计时器中断。当发生计时器中断时,whick_dev的值为2。注意到指向报警处理函数指针可能为空,只有当指针不为空时,才进行相应的处理。代码如下:void usertrap(void) { ... // give up the CPU if this is a timer interrupt. if(which_dev == 2){ if (p->alarm_interval){ p->ticks_count++; if (p->ticks_count == p->alarm_interval && p->flag == 0){ p->alarm_trapframe = *p->trapframe; p->trapframe->epc = (uint64)p->alarm_handler; p->flag = 1; p->ticks_count = 0; } } yield(); } usertrapret(); }每发生一次定时器中断,
ticks_count就加1,如果此时已经达到了报警间隔并且没有正在处理的报警,则设置相应的参数以转至报警处理函数。注意到上述代码的第11行,进程的trapframe->epc保存了进程下一条指令的地址,把其设置为报警处理函数的地址以便进程跳转到报警处理函数。再看到上述代码的第10行,由于进程执行完报警处理函数之后,应该恢复到原来的执行流,故此处的alarm_trapframe保存了进程被中断时相关的寄存器。设置flag以标记本次报警处理还未完成。 -
实现
sys_sigalarm函数,该函数有两个参数(报警间隔和报警处理函数的指针),分别给进程的两个成员赋值即可。代码如下:uint64 sys_sigalarm(void) { struct proc *p = myproc(); if (argint(0, &p->alarm_interval) < 0 || argaddr(1, (uint64*)&p->alarm_handler) < 0) return -1; /* printf("%d %d\n", p->alarm_interval, p->alarm_handler); */ return 0; } -
实现
sys_sigreturn函数,由于报警处理函数结束后,需要恢复进程被定时器中断时的执行流,把p->trapframe恢复到p->alarm_trapframe。该函数被调用时,标志着报警处理函数已经结束,所以应该把flag设置为0。代码如下:uint64 sys_sigreturn(void) { struct proc *p = myproc(); p->flag = 0; *p->trapframe = p->alarm_trapframe; return 0; } -
在分配进程的
allocproc函数中添加新字段的初始化:static struct proc* allocproc(void) { ... found: ... p->flag = 0; p->alarm_interval = 0; p->ticks_count = 0; ... return p; }

浙公网安备 33010602011771号