当前位置: 首页 > wzjs >正文

中山哪里有做网站苏州市住房和城乡建设局投折网站

中山哪里有做网站,苏州市住房和城乡建设局投折网站,南京网络优化公司有哪些,用dw做网站的流程url: https://pdos.csail.mit.edu/6.S081/2020/labs/lazy.html 操作系统利用页表硬件可以实现诸多巧妙技巧,其中之一便是用户空间堆内存的惰性分配。Xv6应用程序通过sbrk()系统调用向内核申请堆内存。在我们提供的基准内核中,sbrk()会直接分配物理内存并…

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


操作系统利用页表硬件可以实现诸多巧妙技巧,其中之一便是用户空间堆内存的惰性分配。Xv6应用程序通过sbrk()系统调用向内核申请堆内存。在我们提供的基准内核中,sbrk()会直接分配物理内存并将其映射到进程的虚拟地址空间。对于大规模内存请求,内核执行分配和映射操作可能耗时极长——例如1GB内存相当于262,144个4096字节的页,即便单次分配开销很小,如此庞大的数量级也令人望而生畏。更何况,某些程序分配的内存会超出实际使用量(比如实现稀疏数组时),或者过早提前分配内存。为了让sbrk()在这些场景下能快速返回,成熟的内核会采用惰性分配策略:即sbrk()调用时不立即分配物理内存,仅记录被分配的用户地址范围,并在用户页表中将这些地址标记为无效。当进程首次尝试访问任一惰性分配的内存页时,CPU会触发缺页异常,此时内核才真正分配物理内存、进行清零操作并建立映射。本实验将为xv6实现这一惰性分配特性。
这段总结:直接分配内存开销大,且遇到用户进程分配过多内存 crash 时会造成 overhead 浪费。因此采用 lazy allocation (记录已分配的范围 + 缺页异常)

这次实验相关的代码:

  • kernel/trap.c
  • kernel/vm.c
  • kernel/sysproc.c

任务1:Eliminate allocation from sbrk() (easy) (完成)

你的首要任务是从 sbrk(n) 系统调用的实现(即 sysproc.c 中的 sys_sbrk() 函数)中移除物理页分配逻辑。sbrk(n) 系统调用会将进程的内存大小(size)增加 n 字节,并返回新分配区域的起始地址(即原先的内存大小)。修改后的 sbrk(n) 应当仅将进程的 myproc()->sz 增加 n 并返回旧的大小值,而不再实际分配内存——因此你需要删除对 growproc() 的调用(但仍需确保进程的 size 正确增长!)。

尝试猜测这一修改会导致什么结果:哪些功能会出问题?
回答:会导致缺页异常

进行此修改后,启动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。
回答:导致缺页错误的原因是用户程序访问了一个实际上没有被映射到内存空间的地址

把 sysproc.c 的 sys_sbrk 修改如下:

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

运行 echo hi 后报错如下:
基本与讲义一致

$ echo hi
usertrap(): unexpected scause 0x000000000000000f pid=3sepc=0x00000000000012ac stval=0x0000000000004008
panic: uvmunmap: not mapped

任务2:Lazy allocation (moderate) (完成)

修改 trap.c 中的代码,使其能够处理用户空间的缺页错误:在触发缺页的地址处映射一个新分配的物理内存页,然后返回到用户空间,让进程继续执行。你应该在生成 “usertrap(): …” 消息的 printf 调用之前添加你的代码。同时,根据需要修改其他 xv6 内核代码,以确保 echo hi 能够正常工作。

以下是一些提示:

  • 您可以通过在usertrap()中检查r_scause()是否为13或15来确定故障是否为页面错误。
    syscall();} else if(r_scause() == 13 || r_scause() == 15) {// load page fault 和 write page fault}else if((which_dev = devintr()) != 0){// ok} else {
  • r_stval()返回RISC-V stval寄存器的值,其中包含导致页面错误的虚拟地址。
  } else if(r_scause() == 13 || r_scause() == 15) {// load page fault 和 write page fault// 使用 stval 获取发生缺页异常的用户空间虚拟地址uint64 va = r_stval();}
  • 从vm.c中的uvmalloc()中窃取代码,这是sbrk()调用的(通过growproc())。您需要调用kalloc()和mappages()。
  • 使用PGROUNDDOWN(va)将错误的虚拟地址向下舍入到页边界。
  } else if(r_scause() == 13 || r_scause() == 15) {// load page fault 和 write page fault// 使用 stval 获取发生缺页异常的用户空间虚拟地址uint64 va = r_stval();// 获取虚拟地址下界va = PGROUNDDOWN(va);// 分配一页char *mem = kalloc();if(mem == 0)panic("no memory when page fault in usertrap");// 置空一页memset(mem, 0, PGSIZE);// 把这一页映射给用户空间 vaif(mappages(p->pagetable, va, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0)panic("mapping failure when page fault in usertrap");}
  • uvmunmap()将会panic;修改它,如果某些页面未映射,则不会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){// 如果某些页面未映射,则不会panic。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;}
}
  • 如果内核崩溃,请在kernel/kernel.asm中查找sepc。
  • 使用您在pgtbl实验中的vmprint函数来打印页表的内容。
  • 如果您看到错误“incomplete type proc”,请包含“spinlock.h”然后是“proc.h”。

如果一切顺利,您的懒惰分配代码应该会使echo hi工作。您应该至少得到一个页面错误(以及懒惰分配),也许两个。

经过测试,echo hi 顺利工作了
在这里插入图片描述


任务3:Lazytests and Usertests (moderate) (doing)

我们已经为您提供了lazytests,这是一个xv6用户程序,用于测试可能对您的懒惰内存分配器造成压力的一些特定情况。修改您的内核代码,以便lazytests和usertests都能通过。

  • 处理负sbrk()参数。
uint64
sys_sbrk(void)
{int addr;int n;if(argint(0, &n) < 0)return -1;struct proc* p = myproc();if(n >= 0) {addr = p->sz;p->sz += n;}else {if(p->sz + n < 0)return -1;addr = p->sz;p->sz = uvmdealloc(p->pagetable, p->sz, p->sz + n);}return addr;
}
  • 如果一个进程在用sbrk()分配的虚拟内存范围之外的地址上发生页面错误,则杀死该进程。
  } else if(r_scause() == 13 || r_scause() == 15) {// load page fault 和 write page fault// 使用 stval 获取发生缺页异常的用户空间虚拟地址uint64 va = r_stval();// 如果一个进程在用sbrk()分配的虚拟内存范围之外的地址上发生页面错误,则杀死该进程。if(va >= p->sz)p->killed = 1;// 获取虚拟地址下界va = PGROUNDDOWN(va);// 分配一页char *mem = kalloc();...
  • 正确处理fork()中的父进程到子进程的内存复制。

进入 kernel/proc.c : fork 源码查看,发现使用 uvmcopy 拷贝用户内存到子进程,进入 uvmcopy 查看,修改如下:

  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)...
  • 处理进程将sbrk()的有效地址传递给read或write等系统调用,但该地址的内存尚未分配的情况。

之前处理 page fault 是在 trap.c : usertrap 里处理的。这种处理方式只能处理用户程序发生的缺页异常,而无法处理 read/write 等系统调用在内核发生缺页时的错误。

以 write 系统调用为例,在内核中的调用链:sys_write → filewrite → writei → either_copyin → copyin。在 copyin 中使用 walkaddr 查找虚拟地址的物理地址。此时由于没有映射,walkaddr 就会返回0。所以这里要做页表映射,如下:

int
copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
{uint64 n, va0, pa0;while(len > 0){va0 = PGROUNDDOWN(srcva);pa0 = walkaddr(pagetable, va0);if(pa0 == 0) {struct proc* p = myproc();if(srcva >= p->sz) return -1;// 缺页异常,做页表映射// 分配一页char *mem = kalloc();if(mem == 0) return -1;// 清空这页memset(mem, 0, PGSIZE);// 把这一页映射给用户空间 vaif(mappages(p->pagetable, va0, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0)panic("mapping failure when page fault in copyin");// 再查找一次物理地址pa0 = walkaddr(pagetable, va0);}n = PGSIZE - (srcva - va0);if(n > len)n = len;memmove(dst, (void *)(pa0 + (srcva - va0)), n);len -= n;dst += n;srcva = va0 + PGSIZE;}return 0;
}

同理可分析 read 系统调用,copyout 做相似的修改即可

这里很难使用 kernelvec + 页表硬件去实现缺页异常。主要是无法判断缺页异常的 stval 来自于用户空间虚拟地址还是内核空间虚拟地址

  • 正确处理内存不足的情况:如果在页面错误处理程序中kalloc()失败,则杀死当前进程。
  • 处理比用户栈栈顶更低的无效地址的页面故障。

加一个判断就行

  } else if(r_scause() == 13 || r_scause() == 15) {// load page fault 和 write page fault// 使用 stval 获取发生缺页异常的用户空间虚拟地址uint64 va = r_stval();// 如果一个进程在用sbrk()分配的虚拟内存范围之外的地址上发生页面错误,则杀死该进程。// 处理比用户栈栈顶更低的无效地址的页面故障。if(va >= p->sz || va < p->trapframe->sp)p->killed = 1;// 获取虚拟地址下界va = PGROUNDDOWN(va);// 分配一页char *mem = kalloc();if(mem == 0) {p->killed = 1;// panic("no memory when page fault in usertrap");}else {// 置空一页memset(mem, 0, PGSIZE);// 把这一页映射给用户空间 vaif(mappages(p->pagetable, va, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0)panic("mapping failure when page fault in usertrap");}}

用户栈下方的无效页面故障只能是发生在用户态的异常,故可知该异常由 usertrap() 处理。
从 memlayout.h 可以看到用户程序的地址空间排布

// User memory layout.
// Address zero first:
//   text
//   original data and bss
//   fixed-size stack
//   expandable heap
//   ...
//   TRAPFRAME (p->trapframe, used by the trampoline)
//   TRAMPOLINE (the same page as in the kernel)

p→trapframe→sp

TODO: here

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

$  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
$

TODO: here



文章转载自:

http://t5egHQbV.xqjrg.cn
http://CrNP1fpe.xqjrg.cn
http://clWOyjGS.xqjrg.cn
http://tZhfqvSN.xqjrg.cn
http://pivfc6Rd.xqjrg.cn
http://marlgrRq.xqjrg.cn
http://catUdLIw.xqjrg.cn
http://YCKxRsv8.xqjrg.cn
http://0mlWfRob.xqjrg.cn
http://s7aXJQhu.xqjrg.cn
http://Bn4slDeH.xqjrg.cn
http://rGmBCpHk.xqjrg.cn
http://GyaIlodo.xqjrg.cn
http://jQq2LwmV.xqjrg.cn
http://RCPa2DKD.xqjrg.cn
http://WVK7jjST.xqjrg.cn
http://a1Js4Ecg.xqjrg.cn
http://esXAk5ir.xqjrg.cn
http://qzSyiHAR.xqjrg.cn
http://ayvTVRHe.xqjrg.cn
http://mVhZk0PX.xqjrg.cn
http://05XmIrhZ.xqjrg.cn
http://hpS9hqsk.xqjrg.cn
http://FTH5RdD5.xqjrg.cn
http://p3ZYUXIK.xqjrg.cn
http://X0Bz3e6D.xqjrg.cn
http://J6kQuCVr.xqjrg.cn
http://3JYdHZvK.xqjrg.cn
http://holIr8wV.xqjrg.cn
http://hqfygwRt.xqjrg.cn
http://www.dtcms.com/wzjs/704856.html

相关文章:

  • 商城类的网站怎么做做网站的术语
  • 品牌商城网站制作公司网站优化公司收费
  • 做网站一定要注册域名吗58同城推广代运营
  • html网站模板建站电脑虚拟主机
  • 免费网站空间 国外鹰潭做网站
  • 无锡怎么做网站推广网站外链建设实例
  • 做配资 怎么在网站联系客户wordpress评论img标签
  • 怎么建设一个漫画网站百度找不到 网站
  • 汉中专业网站建设价格网站推广排名优化多少钱
  • 网站中文商标域名注册网站推广方案策划书2000
  • 广州做网站找哪个公司好网站开发开发优势
  • 邯郸网站设计在哪里广州有哪些旅游景点比较出名
  • 重庆博达建设集团股份有限公司网站网站开发技术员
  • 网站内存不足做网站播放未上映的电影
  • 做logo什么网站免费送衣服在哪个网站做
  • 佛山专业的做网站的网站建设的指导思想
  • 国外浏览器网站哔哩哔哩网页版缓存视频在哪里
  • 文本网站开发英文文献房地产互联网推广
  • 北京专业网站建设公司哪家好百度官网app下载
  • 杭州网站建设公司有哪几家专业建设规划及实施方案
  • 赵县住房和城乡建设局网站首页注册网站免费注册邮箱
  • 建设银行在上海的招聘网站好兄弟资源网在线看片
  • 胶州网站搭建公司网站设计联系电话
  • 微信公众号的激活方法宁波seo搜索平台推广专业
  • 做网站需要知道什么银河盛世网站建设
  • 太原网站建设 thinkphp3.2wordpress主题模板文件下载
  • wordpress 侧导航栏网站结构如何优化
  • 金龙网站哪里建设的好的企业型网站模板下载
  • seo网站关键词优化价格手机上打开html的软件
  • 网站域名做固定资产怎么处理114网站制作