6.s081 traps & lazy allocation实验记录
/ / 点击 / 阅读耗时 4 分钟说明
本文仅作为个人学习的记录,如果你还没有完成相应的实验,不建议阅读本文。
Traps
本实验分为三个部分,第一个部分是回答关于riscv的一些问题,按下不表;第二个部分是实现一个简单的backtrace
,最后一个部分是实验的主体——实现一个定时器事件系统调用。
backtrace实现
了解riscv的ABI中关于stack frame的部分即可:
fp中保存的是当前的stack frame的基址,fp-8位置保存的是返回地址,fp-16部分保存的是上一个fp。
判断当前fp是否是栈底部(xv6中给栈一共分配了一页的空间),如果不是,那么递归输出return address即可。
Alarm实现
Alarm分为两个部分——注册回调、返回。
注册回调
注册回调部分通过sigalarm
实现,其传入tick period以及handler。其中tick period指明了过多少个tick调用一次回调函数,handler是回调函数的地址。
显然,我们需要在内核态保存关于当前tick的信息(实际上内核维护了一个cpu tick的信息,应该也可以使用这个值进行做差),同时记录handler的地址。每发生一次timer interrupt,tick++,当当前进程的tick period达到时,修改epc使得进程通过usertrapret()返回到handler中。
返回
当handler执行完成之后, 如果不做特殊处理,handler可能返回到一个莫名其妙的地方。我们希望handler执行完成之后,跳转回timer interrupt发生的现场继续执行——换而言之,我们需要在切换到handler的那一次usertrapret中记录当前的trapframe,通过调用sigreturn,恢复trapframe,从而跳转到timer interrupt的现场。
注意点
- handler在执行过程中不可以再次被打断(试想再次被打断,trapframe会被冲掉!也就回不到之前的现场了。当然可以用一个栈保存现场……);
Lazy Page Allocation
其实我觉得xv6这个实验,你只要懂英文,照着manual做都能做满分
简单说来,需要在xv6 kernel上修改的核心内容:
- sbrk系统调用:不再分配page,如果参数为负,需要减少page
- usertrap:添加对page fault的处理
- page fault: 判断合法性(是否是invalid page)后分配page
- 内核中涉及address的地方:判断地址合法性