Lazy allocation (moderate)
在生成“usertrap(): …”消息的printf调用之前添加代码
在usertrap()中查看r_scause()的返回值是否为13或15来判断该错误是否为页面错误
通过r_stval()读取stval寄存器中保存的造成页面错误的虚拟地址
参考vm.c中的uvmalloc()中的代码
这是一个sbrk()通过growproc()调用的函数。
对kalloc()和mappages()进行调用
使用PGROUNDDOWN(va)将出错的虚拟地址向下舍入到页面边界
diff --git a/kernel/trap.c b/kernel/trap.c
index a63249e..dfecb97 100644
--- a/kernel/trap.c
+++ b/kernel/trap.c
@@ -65,6 +65,20 @@ usertrap(void)
intr_on();
syscall();
} else if(r_scause() == 13 || r_scause() == 15){
char *pa;
if((pa = kalloc()) != 0) {
uint64 va = PGROUNDDOWN(r_stval());
memset(pa, 0, PGSIZE);
if(mappages(p->pagetable, va, PGSIZE, (uint64)pa, PTE_W|PTE_R|PTE_U) != 0) {
kfree(pa);
printf("usertrap(): mappages() failed\n");
p->killed = 1;
}
} else {
printf("usertrap(): kalloc() failed\n");
p->killed = 1;
}
} else if((which_dev = devintr()) != 0){
// ok
} else {
uvmunmap()会导致系统panic崩溃
修改当前uvmunmap()保证正常运行
diff --git a/kernel/vm.c b/kernel/vm.c
index bccb405..9263460 100644
--- a/kernel/vm.c
+++ b/kernel/vm.c
@@ -183,7 +183,8 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
if((pte = walk(pagetable, a, 0)) == 0)
panic("uvmunmap: walk");
if((*pte & PTE_V) == 0)
panic("uvmunmap: not mapped");
// panic("uvmunmap: not mapped");
continue;
if(PTE_FLAGS(*pte) == PTE_V)
panic("uvmunmap: not a leaf");
if(do_free){
测试
bash
init: starting sh
$ echo hi
hi