文章目录
实验链接
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;
}
Lazy allocation
-
更改文件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; } ....
-
更改文件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; } }
-
执行结果:
Lazytests and Usertests
按照提示进行修改即可。
-
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; }
-
文件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 {
-
文件 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; }
-
查看结果
提交结果
$ git commit -m "lab page tabls"
$ make handin
查看结果
登录网站https://6828.scripts.mit.edu/2020/handin.py/student
,可以看到提交的结果。
常用命令
ctrl + a c
,进入qemu的console页面;- 在console页面,输入
info mem
,可以打印当前的page table。
- 在console页面,输入
参考链接
Github
https://github.com/aerfalwl/mit-xv6-labs-2020.git