Lab5: xv6 lazy page allocation

这个实验相对其他实验来说还是较为简单的,再加上老师上课直接演示了一半,所以这里直接放操作了

文章目录

  • Lab5: xv6 lazy page allocation
    • Eliminate allocation from sbrk() (easy)
    • Lazy allocation (moderate)
    • Lazytests and Usertests (moderate)

操作系统可以使用页表硬件的技巧之一是延迟分配用户空间堆内存(lazy allocation of user-space heap memory)。Xv6应用程序使用sbrk()系统调用向内核请求堆内存。在我们给出的内核中,sbrk()分配物理内存并将其映射到进程的虚拟地址空间。内核为一个大请求分配和映射内存可能需要很长时间。例如,考虑由262144个4096字节的页组成的千兆字节;即使单独一个页面的分配开销很低,但合起来如此大的分配数量将不可忽视。此外,有些程序申请分配的内存比实际使用的要多(例如,实现稀疏数组),或者为了以后的不时之需而分配内存。为了让sbrk()在这些情况下更快地完成,复杂的内核会延迟分配用户内存。也就是说,sbrk()不分配物理内存,只是记住分配了哪些用户地址,并在用户页表中将这些地址标记为无效。当进程第一次尝试使用延迟分配中给定的页面时,CPU生成一个页面错误(page fault),内核通过分配物理内存、置零并添加映射来处理该错误。您将在这个实验室中向xv6添加这个延迟分配特性。

Eliminate allocation from sbrk() (easy)

你的首项任务是删除sbrk(n)系统调用中的页面分配代码(位于***sysproc.c***中的函数sys_sbrk())。sbrk(n)系统调用将进程的内存大小增加n个字节,然后返回新分配区域的开始部分(即旧的大小)。新的sbrk(n)应该只将进程的大小(myproc()->sz)增加n,然后返回旧的大小。它不应该分配内存——因此您应该删除对growproc()的调用(但是您仍然需要增加进程的大小!)。

试着猜猜这个修改的结果是什么:将会破坏什么?

进行此修改,启动xv6,并在shell中键入echo hi。你应该看到这样的输出:

init: starting sh
$ echo hi
usertrap(): unexpected scause 0x000000000000000f pid=3sepc=0x0000000000001258 stval=0x0000000000004008
va=0x0000000000004000 pte=0x0000000000000000
panic: uvmunmap: not mapped

usertrap(): …”这条消息来自***trap.c***中的用户陷阱处理程序;它捕获了一个不知道如何处理的异常。请确保您了解发生此页面错误的原因。“stval=0x0..04008”表示导致页面错误的虚拟地址是0x4008

过于简单,lec8上课演示过

uint64
sys_sbrk(void)
{int addr;int n;if(argint(0, &n) < 0)return -1;addr = myproc()->sz;myproc()->sz += n;//if(growproc(n) < 0)//  return -1;return addr;
}

Lazy allocation (moderate)

YOUR JOB

修改trap.c中的代码以响应来自用户空间的页面错误,方法是新分配一个物理页面并映射到发生错误的地址,然后返回到用户空间,让进程继续执行。您应该在生成“usertrap(): …”消息的printf调用之前添加代码。你可以修改任何其他xv6内核代码,以使echo hi正常工作。

提示:

  • 你可以在usertrap()中查看r_scause()的返回值是否为13或15来判断该错误是否为页面错误
  • stval寄存器中保存了造成页面错误的虚拟地址,你可以通过r_stval()读取
  • 参考***vm.c***中的uvmalloc()中的代码,那是一个sbrk()通过growproc()调用的函数。你将需要对kalloc()mappages()进行调用
  • 使用PGROUNDDOWN(va)将出错的虚拟地址向下舍入到页面边界
  • 当前uvmunmap()会导致系统panic崩溃;请修改程序保证正常运行
  • 如果内核崩溃,请在***kernel/kernel.asm***中查看sepc
  • 使用pgtbl lab的vmprint函数打印页表的内容
  • 如果您看到错误“incomplete type proc”,请include“spinlock.h”然后是“proc.h”。

如果一切正常,你的lazy allocation应该使echo hi正常运行。您应该至少有一个页面错误(因为延迟分配),也许有两个。

修改usertrap

else if (r_scause() == 13 || r_scause() == 15) { // 参考课程的例子,注意判断是否合法(例子没有)uint64 va = r_stval();uint64 ka = (uint64)kalloc();if (ka == 0) {p->killed = 1;}else if(isValid(p, va) == 0) {kfree((void*)ka);p->killed = 1;}else {memset((void*)ka, 0, PGSIZE);va = PGROUNDDOWN(va);if (mappages(p->pagetable, va, PGSIZE, ka, PTE_U | PTE_R | PTE_W) != 0) {kfree((void*)ka);p->killed = 1;}}} // 判断va地址是否合法,如果va大于sz或者当虚拟地址比进程的用户栈还小,则不合法。
int isValid(struct proc *p, uint64 va) {uint64 stackbase = PGROUNDDOWN(p->trapframe->sp);if (va >= p->sz || (va < stackbase)) return 0;return 1;
}

修改uvmunmap()

for(a = va; a < va + npages*PGSIZE; a += PGSIZE){ // 某页为分配不报错,跳过if((pte = walk(pagetable, a, 0)) == 0)//panic("uvmunmap: walk");continue;if((*pte & PTE_V) == 0)//panic("uvmunmap: not mapped");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 (moderate)

我们为您提供了lazytests,这是一个xv6用户程序,它测试一些可能会给您的惰性内存分配器带来压力的特定情况。修改内核代码,使所有lazytestsusertests都通过。

  • 处理sbrk()参数为负的情况。
  • 如果某个进程在高于sbrk()分配的任何虚拟内存地址上出现页错误,则终止该进程
  • fork()中正确处理父到子内存拷贝。
  • 处理这种情形:进程从sbrk()向系统调用(如readwrite)传递有效地址,但尚未分配该地址的内存。
  • 正确处理内存不足:如果在页面错误处理程序中执行kalloc()失败,则终止当前进程。
  • 处理用户栈下面的无效页面上发生的错误。

如果内核通过lazytestsusertests,那么您的解决方案是可以接受的:

$ lazytests
lazytests starting
running test lazy alloc
test lazy alloc: OK
running test lazy unmap...
usertrap(): ...
test lazy unmap: OK
running test out of memory
usertrap(): ...
test out of memory: OK
ALL TESTS PASSED
$ usertests
...
ALL TESTS PASSED
$

处理sbrk()为负数,减少相应的内存,就是dealloc相应的内存n,注意n不能大于p->sz

uint64
sys_sbrk(void)
{int addr;int n;if(argint(0, &n) < 0)return -1;struct proc* p = myproc();addr = p->sz;if (n < 0){if (p->sz + n < 0) return -1;else uvmdealloc(p->pagetable, p->sz, p->sz + n);}p->sz += n;//if(growproc(n) < 0)//  return -1;return addr;
}

修改fork(),正确处理父到子内存拷贝

在fork时会调用uvmcopy复制一份父进程的内存,在lazy allocation中可能0->sz中有部分没有真正分配,在uvmcopy中就会导致panic。累次uvmunmap,修改uvmcopy使得在页面不存在时跳过这一页。

for(i = 0; i < sz; i += PGSIZE){if((pte = walk(old, i, 0)) == 0)//panic("uvmcopy: pte should exist");continue;if((*pte & PTE_V) == 0)//panic("uvmcopy: page not present");continue;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;

处理第4种情况,即系统调用(比如write)传入的虚拟地址对应的内存并没有被分配。
首先搞清楚函数执行流程,在调用write后系统trap到内核态,执行copyin来把用户程序va处的内容复制到内核空间,此时若va处并未分配内存,walkaddr会返回0导致系统调用失败。因此我们要做的就是在walkaddr中分配内存。

在walkadress里修改即可

#include "spinlock.h" // 引用头文件proc.h  的时候还要引用 spinlock.h
#include "proc.h"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);if(pte == 0 || (*pte & PTE_V) == 0) {uint64 ka = (uint64)kalloc();if (ka == 0) {return 0;}else if (isValid(p, va) == 0) {kfree((void*)ka);              //注意这里也要kfree,不然会导致内存泄漏return 0;}else {memset((void*)ka, 0, PGSIZE);if (mappages(p->pagetable, PGROUNDDOWN(va), PGSIZE, ka, PTE_U | PTE_R | PTE_W) != 0) {kfree((void*)ka);return 0;}return ka;}}if((*pte & PTE_U) == 0)return 0;pa = PTE2PA(*pte);return pa;
}
lazytests starting
running test lazy alloc
test lazy alloc: OK
running test lazy unmap
test lazy unmap: OK
running test out of memory
test out of memory: OK
ALL TESTS PASSED
...
test sbrkarg: OK
test validatetest: OK
test stacktest: OK
test opentest: OK
test writetest: OK
test writebig: OK
test createtest: OK
test openiput: OK
test exitiput: OK
test iput: OK
test mem: OK
test pipe1: OK
test preempt: kill... wait... OK
test exitwait: OK
test rmdot: OK
test fourteen: OK
test bigfile: OK
test dirfile: OK
test iref: OK
test forktest: OK
test bigdir: OK
ALL TESTS PASSED

完成!

Lab5: xv6 lazy page allocation相关推荐

  1. 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 ...

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

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

  3. MIT 6.S081 lab 5:lazy page allocation

    1 Lab lab 5就是去实现xv6 book 4.6中写的 Lazy page allocation 有个问题:page fault的trap是如何出现的? 1.1 Eliminate alloc ...

  4. Linux page allocation failure 的问题处理 - zone_reclaim_mode

    标签 PostgreSQL , Linux , page allocation failure , 内存 背景 Linux内核分配失败,现象: 内存使用一定量后,HANG. dmesg中可能会有类似这 ...

  5. warn_alloc():page allocation failure问题分析

    关键词:warn_alloc().__GFP_XXX.order.CMA等等. 在内存申请的时候经常会遇到类似" xxx: page allocation failure: order:10 ...

  6. 一次Linux线上系统page allocation failure问题处理实战记录

    作者:arstercz 来源(阅读原文可直达):https://blog.arstercz.com/ 问题说明 近期一台主机报以下 kernel 警告信息: Apr 28 05:30:51 cztes ...

  7. kernel: swapper: page allocation failure. order:1, mode:0x20

    场景:领导电话通知,我们的主站宕机了,到家后从另外一台机器上ssh一直处于等待状态,开始怀疑机器的负载比较高, 后查看监控机器,发现网卡.cpu.nginx连接数.....通通都没有数据了,显然不是负 ...

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

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

  9. 6.S081-6缺页异常 - lazy allocation - Page Fault

    6.S081-6缺页异常Page Fault 这一节课,可以帮我们完成2个实验: 题目要求链接:Lab: xv6 lazy page allocation 对应做法链接:6.S081 Lab4 Laz ...

最新文章

  1. 进程通信学习笔记(System V消息队列)
  2. 为工厂分配用于公司间Invoice的销售范围
  3. 降低Java占用_如何减少JAVA应用程序的CPU使用率?
  4. 初始化资源管理器 winform
  5. 为什么移动卡上到手机上显示无服务器,移动手机卡加密失败然后就没有服务器无聊的时候给手机卡加密因为不知? 爱问知识人...
  6. 迁移实战:一次AntDB(基于pgxl分布式架构的数据库)数据库迁移经验分享
  7. VMware-workstation安装手册
  8. vue axios配置 发起请求加载loading请求结束关闭loading
  9. Atitit web 之道 艾龙著 Atitit web 之道 艾龙艾提拉著v2 saa.docx 1. 第1章 Web编程基础知识 (1) 3 1.1. 1.1 什么是Web (1) 3 1.2.
  10. 【NCD 2019 B】Let me sleep【边双连通分量缩点、树的直径】
  11. 从0开始的Java复健笔记
  12. 计算机软件专业搞腾讯地图,腾讯地图电脑离线版
  13. cad编辑节点快捷键是什么_cad2018快捷键大全
  14. 原版安装Win10 1909专业版 64位MSDN镜像2020 05
  15. 字节跳动薪酬体系最全揭晓|看完我是真酸了,不服不行
  16. 用python计算工资工资_php项目中用python来预测薪资(工资)
  17. 如何压缩视频可以不影响画质
  18. 8万字208道Java经典面试题总结(附答案)
  19. 声纹识别--基础学习笔记
  20. 医学主题词表(Medical Subject Headings, MeSH)

热门文章

  1. 再谈GC1:GC简介,分代与回收算法
  2. 浏览器html5效果测试,8款浏览器对HTML5的支持测试
  3. AGV调度系统实现(一)
  4. 多因素身份认证之手机推送认证
  5. charles常用功能使用说明
  6. 产品经理数据分析入门指南
  7. java SSM 框架 多数据源
  8. 小程序如何生成二维码海报?
  9. 如何在滴滴云 DC2 上搭建 MySQL 服务
  10. 03:成绩排序 个人博客:doubleq.win