MIT6.s081 lab traps
1.RISC-V assembly
1.a2, a1 store 12(f(8)+1)
2.26: 45b1 li a1,12
3.0x630
4.0x30
5.He110 World;
i = 0x726c6400;
no
6.之前a2中保存的值
2.Backtrace
关键:怎么判断用户栈超出栈底?
fp != PGROUNDDOWN(fp)
用户栈只有一页(4KB)的大小,当栈帧到达页表头时即到达栈底
void
backtrace()
{
printf("backtrace:\n");
uint64 fp = r_fp();
while (fp != PGROUNDDOWN(fp)) {
printf("%p\n", *(uint64 *)(fp-8));
fp = *(uint64 *)(fp - 16);
}
return;
}
3.Alarm
// proc.h 添加以下5个字段
struct trapframe *lastframe; // 用于保存报警前的trapframe
int alarm_interval; // 报警间隔
uint64 handler; // 处理函数
int interval_ticks; // 间隔tick
int alarm_flag; // 标记是否报警返回
// proc.c中进程启动时和释放时进行初始化和释放空间
// allocporc
// 初始化间断时间和中断返回地址
p->interval_ticks = 0;
p->alarm_flag = 0;
p->alarm_interval = 0;
p->handler = 0;
// Allocate a last trapframe page.
if((p->lastframe = (struct trapframe *)kalloc()) == 0){
release(&p->lock);
return 0;
}
//freeproc
if(p->lastframe)
kfree((void*)p->lastframe);
p->lastframe = 0;
// sysproc.c
// 警报
uint64
sys_sigalarm(void)
{
int n;
uint64 handler_pointer = 0;
struct proc *cur_proc = myproc();
if(argint(0, &n) < 0 || argaddr(1, &handler_pointer) < 0)
return -1;
cur_proc->alarm_interval = n;
cur_proc->handler = handler_pointer;
return 0;
}
// 返回
uint64
sys_sigreturn(void)
{
struct proc *cur_proc = myproc();
if (cur_proc->alarm_flag) {
cur_proc->interval_ticks = 0;
*cur_proc->trapframe = *cur_proc->lastframe;
cur_proc->alarm_flag = 0;
}
return 0;
}
// trap.c的usertrap
// 处理进程报警滴答
if(which_dev == 2) {
p->interval_ticks ++;
if ((p->alarm_interval != 0) && (p->alarm_flag == 0) && (p->interval_ticks == p->alarm_interval)) {
p->alarm_flag = 1;
*p->lastframe = *p->trapframe;
p->trapframe->epc = p->handler;
}
}
4.结果
合集:
mit6.s081
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通