首页 > 其他分享 >[MIT 6.S081] Lab: xv6 lazy page allocation

[MIT 6.S081] Lab: xv6 lazy page allocation

时间:2024-02-04 19:56:14浏览次数:28  
标签:uint64 lazy return pte Lab PGSIZE pa myproc MIT

Lab: xv6 lazy page allocation

Eliminate allocation from sbrk()

这一步比较简单,直接在 sys_sbrk 中将分配内存改为对内存大小进行修改而不分配内存即可。

uint64
sys_sbrk(void)
{
  int addr;
  int n;

  if (argint(0, &n) < 0)
    return -1;
  addf = myproc()->sz;
  myproc()->sz += n;

  return 0;
}

Lazy allocation

在这个任务中,我们要实现的是延迟分配内存。在上一个任务中,我们只是实现了 sys_sbrk 的延迟分配,此时依然不能正常运行 echo hi ,现在我们要实这个操作。

在上个任务完成后,进程如果要访问扩容的内存时,这块内存还未被分配,理所应当的会造成缺页中断了。关于缺页中断,我们需要检查 scause 中的错误类型是什么,也就是 1315 ,一个是加载页面错误,一个是保存页面错误。

我们根据运行后得到的错误信息,看一下 usertrap 中关于处理错误的地方,为这个地方添加一个能够处理这两个错误的东西。既然是缺页中断,那么这边就需要处理一下缺页的情况,也就是给它分配页面。

// kernel/vm.c
int lazy_alloc_page(struct proc *p, uint64 vaddr) {
  uint64 va = PGROUNDDOWN(vaddr);
  uint64 pa = (uint64)kalloc();
  if (pa == 0) 
    return -1;
  memset((void *)pa, 0, PGSIZE);
  if (mappages(p->pagetable, va, PGSIZE, pa, PTE_W | PTE_R | PTE_U) != 0) {
    kfree((void *)pa);
    return -1;
  }
  return 0;
}

// kernel/trap.c
void usertrap(void) {
  ...
  } else if (r_scause() == 13 || r_scause() == 15) {
    if (lazy_alloc_page(myproc(), r_stval()) != 0) {
      p->killed = 1;
    }
  } else {
  ...
}

此时我们尝试运行一下 echo hi ,会发现产生一个 panic: uvmunmap: not mapped 我们需要修改一下这里。转到 kernel/vm.c 。我们继续看 uvmunmap 函数,因为是懒分配的页面,那么这里的 pte 并不一定是有效的,因此我们需要直接改为 continue ,因为它暂时还未被分配。同时,我们还要注意到,如果采取了懒分配的方式,那么意味着在页表中可能找不到指定的 pte ,因为它还未被分配,因此第一个 panic 也要改为 continue

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)
      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;
  }
}

再次运行 echo hi ,此时工作正常。

Lazytests and Usertests

我们目前只是实现了一个很简单的功能,按照 hint 的提示,我们还需要补充一些功能。

目前我们的 sbrk 只是简单的加上了 n ,因此我们需要修改一下这里的实现,让它能够根据 n 为正还是负,适应两种情况。

对于 n >= 0 ,那我们直接加就好。对于 n < 0 ,我们就需要判断一下这个大小是否会把内存大小减到负数,如果会,那么说明无效,否则就要将减少的内存回收一下。

uint64 sys_sbrk(void)
{
  int addr;
  int n;

  if(argint(0, &n) < 0)
    return -1;
  addr = myproc()->sz;

  if (n > 0) {
    myproc()->sz += n;
  } else if (myproc()->sz > (uint64)(-n)) {
    uvmdealloc(myproc()->pagetable, myproc()->sz, myproc()->sz + n);
    myproc()->sz += n;
  } else {
    return - 1;
  }
  
  return addr;
}

接着,我们要判断一下缺页的虚拟地址到底发生在哪里。如果这个虚拟地址发生在栈地址,那么说明无效;如果这个虚拟地址超过了分配给这个进程的总内存,那么也是无效。因此,我们要在我们单独添加的 lazy_alloc_page 中先预判一下这个情况。此外,如果这个空间已经分配了,我们不需要再次分配一个页面给它,只需要返回一个 0 ,告诉外部说已经分配好了就行。

int lazy_alloc_page(struct proc *p, uint64 vaddr) {
  // segmentation fault
  if (p->trapframe->sp > vaddr || p->sz <= vaddr)
    return -1;
  // if is already
  if (walkaddr(p->pagetable, vaddr) != 0)
    return 0;
  
  uint64 va = PGROUNDDOWN(vaddr);
  uint64 pa = (uint64)kalloc();

  if (pa == 0)
    return -1;
  memset((void *)pa, 0, PGSIZE);
  if (mappages(p->pagetable, va, PGSIZE, pa, PTE_W | PTE_R | PTE_U) != 0) {
    kfree((void *)pa);
    return -1;
  }

  return 0;
}

接着如果试着运行一下,会发现在 uvmcopy 中出现 panic ,观察源码可以发现,这里也需要更改一下,因为延迟分配的存在,使得这里会造成 pte 还没有或无效的情况。

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)
      // 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;

 err:
  uvmunmap(new, 0, i / PGSIZE, 1);
  return -1;
}

到目前为止,我们现在的修改只有一个测试点 sbrkarg 无法通过,这个问题是系统调用时,所传入的正确地址还未被分配导致的(也就是 hint 第四点)。我们需要检查一下系统调用的参数,看看地址是否未被分配,若未被分配,则尝试为其分配一下。问题是我们要在哪里知道这个参数在哪里得到的?观察一些系统调用获取参数的方式,都是通过 argint 或者 argaddr 之类的方式得到的,因此我们要在 argaddr 分配一下内存即可。

int argaddr(int n, uint64 *ip) {
  uint64 addr = argraw(n);
  if (walkaddr(myproc()->pagetable, addr) == 0 
  && lazy_alloc_page(myproc(), addr) != 0) {
    return -1;
  }
  *ip = addr;
  return 0;
}

Grade

标签:uint64,lazy,return,pte,Lab,PGSIZE,pa,myproc,MIT
From: https://www.cnblogs.com/FlandreScarlet/p/18006896

相关文章

  • MIT 6.1810 Lab: traps
    lab网址:https://pdos.csail.mit.edu/6.828/2022/labs/traps.htmlxv6Book:https://pdos.csail.mit.edu/6.828/2022/xv6/book-riscv-rev3.pdf写前思考我们都知道,在用户进程执行系统调用时,内核代替用户进程执行,那么这种代替是一种什么样的代替。这个过程是还属于用户进程,只是执......
  • 极狐 GitLab 和 Xcode Cloud 集成,实现 iOS 的自动打包
    一直以来,iOS/macOS开发者面临一个难题:大部分云厂商只提供Linux/Windows服务器,而不提供Mac,如果想实现「持续集成自动打包」就需要绑定自己的Mac作为构建机。如果用个人Mac,一旦关机,小组同事就无法构建;如果再买一台公共Mac,又造成浪费。2022年6月,Apple在WWDC(全球开发者......
  • Nand2tetris Part1 lab04-lab06
    概述在前三个lab中,我们构建了hack计算机所需要的基础的芯片。后三个lab则是教我们如何使用这些芯片去搭建一个hack计算机并且使用汇编语言。Week04&Week05把这两个lab放在一起是因为他们给我的感觉更像是知识的互补。lab05教会你汇编语言的规范是什么,lab06则是......
  • MATLAB快速参考
    原文GitHub-MATLAB-cheat-sheet,本文做了翻译和修改MATLAB即MatLABoratory(一做坐一天坐垫实验室)MATrixLABoratory(矩阵实验室)。是一种常用于工程和数学的强大软件,也是一门语言。注意:MATLAB中的函数基本有多种不同参数的重载,本手册只写其中比较常用的方法,实际使用时可以善......
  • gitlab 502问题解决
    问题现象: Whoops,GitLabistakingtoomuchtimetorespond.Tryrefreshingthepage,orgoingbackandattemptingtheactionagain.PleasecontactyourGitLabadministratorifthisproblempersists. 问题定位分析:一、查看系统资源使用情况磁盘满了g......
  • 读论文-协同过滤技术综述(A Survey of Collaborative Filtering Techniques)
    前言今天读的一篇论文题目为《协同过滤技术综述》(ASurveyofCollaborativeFilteringTechniques),文章发表于《人工智能研究进展》(AdvancesinArtificialIntelligence)。要引用这篇论文,请使用下述格式:XiaoyuanSu,TaghiM.Khoshgoftaar,"ASurveyofCollaborativeF......
  • Gitlab Prometheus 磁盘空间占用
    gitlab默认启用Prometheus,数据存储时长是15天,经观察磁盘占用较大(我这边平均每天1G)如果磁盘紧张的情况下可以修改数据保留时长,或直接关闭Prometheus监控,修改配置文件的方法如下:配置文件位置gitlab/config/gitlab.rb1、修改保留天数,下面的配置内容默认全部是注释掉的,可以去......
  • aria-label的作用是什么?
    aria-label的作用是什么?aria-label属性在网页无障碍(WebAccessibility,简称A11Y)中扮演着至关重要的角色。其主要作用如下:提供非视觉提示:aria-label用于为HTML元素提供一个简短、明确的文本描述,这个描述不会在页面上显示出来,但会被屏幕阅读器等辅助技术读取。这意味着视力受损......
  • mit6.824lab2D-Debug记录
    1.死锁要提交快照的时候由于没有人取走applyCh通道里面的东西,导致死锁。具体解释:2D的测试代码中在日志达到一定大小时会调用snapshot,该函数需要申请rf.mu这个互斥锁。而在提交普通的日志条目时,错误地没有先释放锁,导致snapshot无法进行下去,相关的进程卡在rf.mu这个锁上,无法完成......
  • CTFer——文件操作与upload-labs解析
    一、什么是webshellwebshell就是以aspx、php、jsp等网页文件形式存在的一种命令环境也可以将其称为一种网页后门 黑客在入侵网站后,通常会将jsp、aspx或php后门文件与网站服务器web目录下正常的网页文件混在一起然后就可以使用浏览器来访问后门文件,得到一个命令执行环境,以达......