Skip to content

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