• 2020 MIT6.s081 Lab: xv6 lazy page allocation



    实验链接

    https://pdos.csail.mit.edu/6.S081/2020/labs/lazy.html


    实验

    Eliminate allocation from sbrk()

    该题比较简单,只需要在文件kernel/syspro.c文件中,将函数sys_fork改为如下内容即可(只增减proc的大小,不实际分配物理内存):

    uint64
    sys_sbrk(void)
    {
      int addr;
      int n;
    
      if(argint(0, &n) < 0)
        return -1;
      addr = myproc()->sz;
      myproc()->sz = addr + n;
      return addr;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Lazy allocation

    1. 更改文件kernel/trap.c的usertrap函数。

      
       } else if((which_dev = devintr()) != 0){
          // ok
        // begin+++++   
        } else if (r_scause() == 15 || r_scause() == 13) {
          uint64 va = r_stval();
          if (uvmalloc(p->pagetable, PGROUNDDOWN(va), PGSIZE + PGROUNDDOWN(va)) == 0) {
            p->killed = 1;
          }
        // end+++++   
        } else {
          printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
          printf("            sepc=%p stval=%p\n", r_sepc(), r_stval());
          p->killed = 1;
        }
       ....
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    2. 更改文件kernel/vm.c的uvmunmap函数,在找到无效的叶子节点时,直接跳过,而不是panic。

      void
      uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
      {
        uint64 a;
        pte_t *pte;
      
        if((va % PGSIZE) != 0)
          panic("uvmunmap: not aligned");
      
        for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
          if((pte = walk(pagetable, a, 0)) == 0)
            panic("uvmunmap: walk");
          if((*pte & PTE_V) == 0)
            continue; //+++++++++
          if(PTE_FLAGS(*pte) == PTE_V)
            panic("uvmunmap: not a leaf");
          if(do_free){
            uint64 pa = PTE2PA(*pte);
            kfree((void*)pa);
          }
          *pte = 0;
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
    3. 执行结果:
      在这里插入图片描述


    Lazytests and Usertests

    按照提示进行修改即可。

    1. kernel/sysproc.c文件,修改sys_sbrk函数为如下内容:

      uint64
      sys_sbrk(void)
      {
        uint64 addr;
        int n;
      
        if(argint(0, &n) < 0)
          return -1;
        struct proc* p = myproc();
        addr = p->sz;
        if (p->sz + n >= MAXVA || p->sz + n < 0) {
          return addr;
        }
      
        if (n < 0) {
          uvmdealloc(p->pagetable, addr, addr + n);
        }
        p->sz = p->sz + n;
        return addr;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    2. 文件kernel/trap.c文件,修改usertrap文件为如下内容:

      // ++++ begin ++++++++++
      } else if (r_scause() == 15 || r_scause() == 13) {
          uint64 va = r_stval();
          if (va >= p->sz || va < PGROUNDUP(p->trapframe->sp) || va >= MAXVA) { // pagefault的地址大于sbrk的最大值
            p->killed = 1;
          } else {
            if (uvmalloc(p->pagetable, PGROUNDDOWN(va), PGSIZE + PGROUNDDOWN(va)) == 0) {
              p->killed = 1;
            }
          }
        // ++++ end+++++++++++++++++  
        } else {
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    3. 文件 kernel/vm.c,修改如下内容:

      // begin++++
      #define SYS_sigalarm 22
      #define SYS_sigreturn 23
      // end++++
      
      ...
      uint64
      walkaddr(pagetable_t pagetable, uint64 va)
      {
        pte_t *pte;
        uint64 pa;
        struct proc* p = myproc();
      
        if(va >= MAXVA)
          return 0;
      
        pte = walk(pagetable, va, 0);
        // begin ++++  
        if(pte == 0 || (*pte & PTE_V) == 0) {
      
          if (va >= p->sz || va < PGROUNDUP(p->trapframe->sp) || va >= MAXVA) { // pagefault的地址大于sbrk的最大值
            // p->killed = 1;
            return 0;
          } else {
            if (uvmalloc(p->pagetable, PGROUNDDOWN(va), PGSIZE + PGROUNDDOWN(va)) == 0) {
              // p->killed = 1;
              return 0;
            }
            return walkaddr(p->pagetable, va);
          }
        }
        // end +++ 
        if((*pte & PTE_U) == 0)
          return 0;
        pa = PTE2PA(*pte);
        return pa;
      }
      ...
          
          
      int
      uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
      {
        pte_t *pte;
        uint64 pa, i;
        uint flags;
        char *mem;
      
        for(i = 0; i < sz; i += PGSIZE) {
          if((pte = walk(old, i, 0)) == 0)
            continue; // change 
          if((*pte & PTE_V) == 0)
            continue; // change
          pa = PTE2PA(*pte);
          flags = PTE_FLAGS(*pte);
          if((mem = kalloc()) == 0)
            goto err;
          memmove(mem, (char*)pa, PGSIZE);
          if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){
            kfree(mem);
            goto err;
          }
        }
        return 0;
      
       err:
        uvmunmap(new, 0, i / PGSIZE, 1);
        return -1;
      }    
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
    4. 查看结果
      在这里插入图片描述

      在这里插入图片描述
      在这里插入图片描述

    在这里插入图片描述


    提交结果

    $ git commit -m "lab page tabls"
    $ make handin
    
    • 1
    • 2

    查看结果

    登录网站https://6828.scripts.mit.edu/2020/handin.py/student,可以看到提交的结果。

    在这里插入图片描述


    常用命令

    1. ctrl + a c,进入qemu的console页面;
      1. 在console页面,输入info mem,可以打印当前的page table。

    参考链接


    Github

    https://github.com/aerfalwl/mit-xv6-labs-2020.git

  • 相关阅读:
    【计算机毕业设计】5.网上书店系统maven源码
    mysql进阶:企业数据库安全防护方案
    计算机发展简史
    Spring中自定义类型转换器
    Java使用Socket简单实现FTP
    python日志管理
    C#中使用Bitmap 传递图到C++
    在Windows或Mac上安装并运行LLAMA2
    继承day01
    业聚医疗第三次冲刺港交所上市,钱永勋、刘桂祯夫妇为实控人
  • 原文地址:https://blog.csdn.net/u014110320/article/details/126100213