携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
speed up system calls
加速原理
为实现系统调用加速,操作系统会在用户态和内核态之间通过一种只读方式共享数据,这种只读方式体现为页表,我们要做的是了解页表映射(mapping)的过程。
官方教程指定完成步骤
- 在kernel/proc.c中修改proc_pagetable()文件,参照RISC-V privileged architecture manual 小册子和程序中类似代码,确定权限条件,并使用mappages()
- 在allocproc()函数中分配内存
- 在freeproc中释放内存
官方没有提到需要自己摸索的步骤
- 在kernel/proc.h中的proc结构体中加入struct usyscall*,这里我将变量命名为usyspage。
- 如果仅仅完成了以上几步,make clean会出现"panic: freewalk: leaf",需要解除映射。
所有程序修改到的地方
proc.h
proc.c
proc_pagetbale
allocproc()
注意:新加入的函数应紧跟上一个allocate之后,在empty user page table之前(别问我怎么知道的,我顺序反了,debug了半天)
freeproc()
proc_freepagetable()
运行结果
print a page table
粗读实验要求体会
- 不要打印无效的PTE
- 物理地址的数量可能和示例不同,条目数和虚拟地址的数量应该是相同的(我认为这个体现了所学概念)
需要完成的步骤(注:此处有更新)
在kernel/defs.h中添加vmprint原型,使exec.c能找到这个文件
(笔者2023重做实验时注:其实这个原型应该加在加在vm.c,因为实际函数是写在那里的,不过写在exec.c也没问题,因为只要调用函数的地方引用了defs.h头文件,就能用上这个函数,只是会让其他开发者很困惑。笔者重做时已经修正了这一处代码习惯,这里保留着截图以作诫勉)
修改kernel/vm.c,在其中添加vmprint相关代码,具体可参考freewalk()的写法以及使用 %p
freewalk代码
(上一个环节的报错提示来源,递归调用自身,稍加修改可变成打印详细信息)
vmprint()
主体代码放helper_vmprint()
(更新)在kernel/exec.c的return argc前加入如下代码:
if(p->pid==1) vmprint(p->pagetable)
运行结果
Detecting which pages have been accessed
实验步骤
在kernel/sysproc.c中完善sys_pgaccess()函数。
需要传入三个参数,这里依题意分别设为addr,len,bitmask。
代码具体内容参考其他函数中argaddr()和argint()的用法(lab2中也用到过)
- 分别对addr,len,bitmask进行处理,下标也分别是0,1,2
- 对应hints4中的边界处理
- 核心代码,遍历页表,并调用一个辅助函数vm_pgaccess(后续会提到)
- copyout()对应hints第3点
编写vm_pgaccess(写在vm.c中)
vm.c中的walk()函数可以用作参考
walk()函数如下:
vm_pgaccess()函数如下:
在riscv.h中定义PTE_A
打开文件找到相应位置后,发现其他的定义是这样。
那这个PTE_A可以直接顺接定义为5吗?其实是不行的!
翻看教程提供的这个手册
会发现这里A对应的位置是6。
最后还得在defs.h中添加vm.c那里加入 我们自己加上去的 vm_pgaccess,让系统能找到它
实验结果
make qemu一下
最终结果
make grade之后是这样的:
注意事项:
- 记得自己加入time.txt 和 answers-pgtbl.txt两个文件(评测不看你文件内容,只是看有没有这两个文件
- 如果遇到Test usertests卡住不动的情况,耐心等一等,最终会有的。
- 如果你已经忍不住crtl-c把进程终止了,再make grade后提示gdb端口被占用之类的,按提示输入了那两个命令又不起作用(提示找不到相关进程),只需要重新连接一下当前做实验的设备就行了
结语
以上是我完成实验后照着官网要求回忆步骤并打开相应文件截图的,某些步骤可能会有遗漏。 最后也感谢你能看到这里!