1 Lab

lab 5就是去实现xv6 book 4.6中写的 Lazy page allocation

有个问题:page fault的trap是如何出现的?

1.1 Eliminate allocation from sbrk()

你的第一个任务是在sbrk系统调用中删除页分配的实现部分,这部分内容在 sysproc.c/sys_sbrk()中。sbkr(n)系统调用会给进程增加 n byte的空间,并且返回新空间的起始地址(等于old sz)。新的sbrk(n)应该只给进程的sz增加n,并且返回old sz。并且不会分配任何空间--所以你应该删除growproc()的调用(但是你仍要去增加 p->sz!)。

这个部分是要在调用 sbrk的情况下不分配新的内存页,但是需要修改 p->sz。

我这边选择直接修改 growproc的内容,这个函数除了sbrk 没有其他函数进行调用,所以直接修改。

这边是直接把 n > 0的内容注释掉,加上一条修改sz的。其实本来第一部分的lab,只需要把sbrk调用growproc 去掉,然后修改sz就行了,但是考虑 n < 0的情况,我们是应该直接删除页的,看了后面部分的lab,也确实有这个要求。

// Grow or shrink user memory by n bytes.
// Return 0 on success, -1 on failure.
int
growproc(int n)
{uint sz;struct proc *p = myproc();sz = p->sz;if(n > 0){sz += n;
//    if((sz = uvmalloc(p->pagetable, sz, sz + n)) == 0) {//      return -1;
//    }} else if(n < 0){sz = uvmdealloc(p->pagetable, sz, sz + n);}p->sz = sz;return 0;
}

然后去测试 echo hi,发生了跟他一样的错误。这是为什么呢?然后从头开始找哪调用了sbrk(),最后发现是 shell里面会通过 malloc 给struct cmd分配内存。

1.2 Lazy allocation

这边直接把2、3部分都写在一起了。

通过在发生fault的地址映射新分配的物理页,来修改 trap.c 中与用户空间page fault相关的代码,然后返回用户空间使得进程重新执行。你应该在 打印"usertrap(): ..." 的 printf 调用前添上你的代码。为了使得echo hi运行,你可以修改 xv6 中任何 kernel code。

修改trap.c

这边注意几个点

  • 首先是区分fault的类型,不处理的包括:

    • 非page fault
    • 虚拟地址高于进程sz的
    • 用户栈的保护页,因为用户栈位置与内核栈不同,是在底下的,所以需要当作非alloc部分。还有就是注意从trapframe中去取sp,因为此时的sp应该不是之前的栈指针。
  • 然后就是处理 lazy alloc部分
    • 如果内存不够了,就杀死进程。
    • 参考 uvmalloc,写映射的部分。
//修改 usertrap()里面对异常处理部分
else {uint64 va = r_stval();uint64 sp = p->trapframe->sp;// not a page faultif((r_scause() != 13 && r_scause() != 15) || va >= p->sz || (va < PGROUNDDOWN(sp) && va >= PGROUNDDOWN(sp - PGSIZE))){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;}// lazy allocelse{va = PGROUNDDOWN(va);char* mem;// if kalloc fails,kill the procif((mem = kalloc()) == 0){p->killed = 1;}else{memset(mem,0,PGSIZE);if((mappages(p->pagetable, va, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U)) != 0){kfree(mem);// if fails,unmap and free the pageuvmunmap(p->pagetable,va,1,0);}}}}

修改 vm.c/uvmunmap

在lazy alloc 的情况下,是有可能产生这样的情况:sbrk修改了sz,但是最终没有分配物理内存的情况下,进行了uvmunmap。所以需要修改里面panic的情况:1.没有walk到pte 2.pte是不可访问的

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)continue;
//      panic("uvmunmap: walk");if((*pte & PTE_V) == 0)continue;
//      panic("uvmunmap: not mapped");if(PTE_FLAGS(*pte) == PTE_V)panic("uvmunmap: not a leaf");if(do_free){uint64 pa = PTE2PA(*pte);kfree((void*)pa);}*pte = 0;}
}

修改 vm.c/uvmcopy

类似于 uvmunmap,uvmcopy也要处理这样的情况。

uvmcopy主要是在fork中被调用。如果父进程的有上述的情况,那么它也需要去冷处理page fault。

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;
//      panic("uvmcopy: pte should exist");if((*pte & PTE_V) == 0)continue;
//      panic("uvmcopy: page not present");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;
}

再修改proc.c/growproc

其他改完基本上所有case都能过了,但是那个 sbrkargs过不了。情况应该是在系统调用的时候不会发生page fault的情况,然后就没有办法去分配内存。这边卡了很久,最后查到 write的系统调用函数那边, 但是看不懂~~。最后试了一下每次sbrk 都再多分配一个字节,那么 内存位置 sbrk(),就是有效的。

int
growproc(int n)
{uint sz;struct proc *p = myproc();sz = p->sz;if(n > 0){if((uvmalloc(p->pagetable, sz, sz + 1)) == 0) {return -1;}sz += n;} else if(n < 0){sz = uvmdealloc(p->pagetable, sz, sz + n);}p->sz = sz;return 0;
}

MIT 6.S081 lab 5:lazy page allocation相关推荐

  1. MIT6.S081学习总结-lab5:lazy page allocation

    lab5 是lazy page allocationi相关,主要解决页面错误问题.O/S可以对页表硬件使用的许多巧妙技巧之一是延迟分配用户空间堆内存.Xv6应用程序使用sbrk()系统调用向内核请求堆 ...

  2. MIT 6.S081 lab 11:Networking

    ​ 背景 在你开始写代码前,你可能会发现xv6 book中的第五章:中断和设备驱动是很有帮助的. 你将使用一个叫做E1000的网络设备来处理网络通信.对于xv6(以及你写的驱动),E1000看起来像一 ...

  3. 6.S081 Xv6 Lab 5: lazy page allocation

    Lab: xv6 lazy page allocation https://pdos.csail.mit.edu/6.S081/2020/labs/lazy.html 新的 2020 版哦. $ gi ...

  4. Lab5: xv6 lazy page allocation

    Lab5: xv6 lazy page allocation 这个实验相对其他实验来说还是较为简单的,再加上老师上课直接演示了一半,所以这里直接放操作了 文章目录 Lab5: xv6 lazy pag ...

  5. MIT 6.s081学习笔记

    MIT 6.s081学习笔记 introduction 计算机组织结构: 最底部是一些硬件资源,包括了CPU,内存,磁盘,网卡 最上层会运行各种应用程序,比如vim,shell等,这些就是正在运行的所 ...

  6. MIT 6.S081 实验5 笔记与心得

    Lab 5:Lazy 文章目录 Lab 5:Lazy 前期准备 Eliminate allocation from sbrk() ([easy](https://pdos.csail.mit.edu/ ...

  7. 「实验记录」MIT 6.S081 Lab7 multithreading

    #Lab7: multithreading I. Source II. My Code III. Motivation IV. Uthread: switching between threads ( ...

  8. 【操作系统】MIT 6.s081 LAB5

    Lab5: xv6 lazy page allocation 原文地址:YSBLOG 参考资料: https://juejin.cn/post/7034359064121311240 https:// ...

  9. MIT 6.S081 Lab4 traps

    #Lab4: traps #Source #My Code #Motivation #Backtrace (moderate) #Motivation #Solution #S0 - RISC-V 栈 ...

最新文章

  1. 高德地图区域线显示_护航国庆假期,助力重点区域精细化管理——扬州交警与高德地图联合推出“全境智能”系统...
  2. SparkWeb 编译
  3. mysql5.7+proxy_mysql5.7使用ProxySQL实现读写分离
  4. 重置oracle 11G的system、sys密码
  5. linux数据同步技术比较,linux下实现web数据同步的四种方式(性能比较)教程.docx
  6. MyBatis 3 – Spring集成教程
  7. Promise使用,return的运用,解决回调地狱
  8. 机器学习顶刊文献_“大数据+机器学习”在光催化制氢中的研究范式
  9. WebService开发常用功能详解
  10. centos 之7zip
  11. Baumer工业相机堡盟工业相机如何通过BGAPISDK显示彩色相机和黑白相机的图像(C#)
  12. 想做游戏测试工程师?这几点不知道可不行!
  13. oracle 表变化监控,oracle 怎么 监控数据变化
  14. 【JDK编译】Centos7编译OpenJDK7
  15. pcs增加mysql资源_pcs命令配置示例
  16. 三极管的经典之作,你知道吗?
  17. Android RxJava生命周期管理解决方案整理
  18. 软件工程之软件设计阶段
  19. # 关于Qt程序异常结束, The process was ended forcefully问题
  20. java基础案例教程答案,2021最新版!

热门文章

  1. 《东周列国志》第七回 公孙阏争车射考叔 公子翚献谄贼隐公
  2. VS2005的几个大版本简介
  3. 如何成为一个好的管理领导者--谈唐僧在如来面前吐真言
  4. 后台管理系统、表格、表单
  5. pcb成型板aoi检测_PCB电路板加工技术
  6. Android wifi sniffer log总结分析
  7. Redis 如何实现分布式——京东金融Redis缓存的设计与实践
  8. Mysql中慢查询语句分析
  9. Vue中加载mapv和mapvgl
  10. 小白怎么入门漫画,难学么?