【MIT 6.S081】2020, 实验记录(5),Lab: lazy allocation

news2024/9/24 17:20:39

目录

    • Task 1: Eliminate allocation from sbrk()
    • Task 2: Lazy allocation
    • Task 3: Lazytests and Usertests

在学习了 page fault 这一节课后,了解了操作系统是如何结合 page table 和 trap 利用 page fault 来实现一系列的神奇的功能。这个 lab 就是在 XV6 中实现 lazy allocation 机制

xv6 默认是 eager allocation,也就是用户程序一旦调用 sbrk,内核会立刻分配应用程序所需要的物理内存。这个实验就是将其修改为 lazy allocation,用户在调用 sbrk 时不会立刻分配物理内存,只是做一个记录,等到程序真正读写这个内存 page 时,才会因触发 page fault 而让内核分配一个实际的物理内存并修改到 page table 中。

Task 1: Eliminate allocation from sbrk()

这个 task 让我们删除 sbrk 的系统调用实现函数 sys_sbrk() 中分配物理内存的代码,内核只需要增大 myproc()->sz 这个值即可。

myproc()->sz 这个值记录的当前用户进程已申请的 heap 的最大地址:
sbrk

代码(kernel/sysproc.c):

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

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

make qemu 后执行 echo hi

task-1
这里会发生 page fault,在下面的 task 中,我们将处理发生的 page fault,并为其分配物理内存 page 且修改对应的 page table。

Task 2: Lazy allocation

这个 task 需要修改代码来处理 page fault 并为用户程序分配物理内存。

当 page fault 发生时,程序会通过 trap 机制进入 usertrap() 函数,我们可以在这里实现相关的而逻辑。SCAUSE 寄存器记录了本次 trap 发生的原因,当寄存器的值为 13 或 15 时,表示因 load 或 store 指令访问一个地址但没找到相应 PTE 而发生 page fault,所以我们需要在 usertrap() 函数中判断 SCAUSE 寄存器的值,并实现相应的 page fault 处理逻辑。

首先在 usertrap() 函数(kernel/trap.c)中添加对 page fault 的识别并调用 page fault handler 来处理:

usertrap 函数
添加并实现 page_fault_handler() 函数(代码紧跟在 usertrap 函数后面就可以):

//
// handle page fault
//
void 
page_fault_handler(struct proc * const p)
{
  uint64 va = r_stval();  // 触发 page fault 的虚拟地址
  if (p->sz <= va || va < p->trapframe->sp) {  // 如果 va 高于 sbrk 申请的地址或者低于栈顶地址
    p->killed = 1;
  } else {
    uint64 ka = (uint64) kalloc();
    if (ka == 0) {  // 如果物理内存不足
      p->killed = 1;
    } else {
      memset((void*) ka, 0, PGSIZE);  // 为这块地址填充 0
      va = PGROUNDDOWN(va);  // round the faulting virtual address down to a page boundary.
      // 将 va -> ka 的 mapping 添加到 user page table 中
      if (mappages(p->pagetable, va, PGSIZE, ka, PTE_W | PTE_X | PTE_U | PTE_R) != 0) {
        kfree((void*) ka);
        p->killed = 1;
      }
    }
  }
}

还存在一个问题,因为用户申请的内存并没有一定分配实际的物理内存,所以在对申请但未分配的内存做 unmap 时会产生错误,因此需要对 unmap 的代码进行修改,当想要释放一个未分配的 page 时,代码中只需要直接忽视就可以了(vm.c):

ummap 函数
完成以上修改后,make qemu 之后就可以正常运行 echo hi 了:

task2

Task 3: Lazytests and Usertests

前一个 task 实现了一个简单的 lazy allocation,执行 echo hi 是没问题了,但在更复杂的场景下,仍然有许多需要考虑的事情,本 task 要求完善 lazy allocation 并能够通过 lazytestsusertests 两个测试。

首先为了实现的方便,这里将实际分配物理内存的代码逻辑封装到 alloc_memory_page() 函数(kernel/vm.c)中:

// 分配一个实际物理内存,并映射到 va 中,将这个 mapping 添加到 page table 中
uint64
alloc_memory_page(uint64 va, pagetable_t pagetable)
{
  uint64 ka = (uint64) kalloc();
  if (ka == 0) {  // 如果物理内存不足
    return 0;
  }
  memset((void*) ka, 0, PGSIZE);  // 为这块地址填充 0
  va = PGROUNDDOWN(va);  // round the faulting virtual address down to a page boundary.
  if (mappages(pagetable, va, PGSIZE, ka,  PTE_W | PTE_X | PTE_R | PTE_U) != 0) {
    kfree((void*) ka);
    return 0;
  }
  return ka;
}

这个函数通过 kalloc() 来分配一个物理内存 page,并将其映射到 va 中,然后将这个 mapping 添加到 page table 中。当成功时,函数返回分配的物理内存地址,当失败时(内存不足或添加 mapping 失败),函数返回 0。

我们将这个 alloc_memory_page() 函数的声明放到 defs.h 头文件中。

有了这个 alloc_memory_page 函数,我们在上一个实验写的 page fault handler 就可以简化一下了,分配物理内存的逻辑改为调用 alloc_memory_page 即可:

//
// handle page fault
//
void 
page_fault_handler(struct proc * const p)
{
  uint64 va = r_stval();
  if (p->sz <= va || va < p->trapframe->sp) {  // 如果 va 高于 sbrk 申请的地址或者低于栈顶地址
    p->killed = 1;
  } else {
    if (alloc_memory_page(va, p->pagetable) == 0) {  // 当分配内存或添加 mapping 失败,就直接杀死该进程
      p->killed = 1;
    }
  }
}

修改 uvmummap() 函数,当无法从 page table 中找到 va 的 PTE 时或者 PTE 未映射时,直接跳过:

uvmunmap
我们还需要正确处理 fork 时父进程向子进程 copy 内存的逻辑,这里需要修改 uvmcopy() 函数,也是在页表不存在或 PTE 未映射时直接跳过:

uvmcopy
还有一种情况是,当用户程序把通过 sbrk() 申请的内存(但还未实际分配)的内存地址传递给系统调用时,kernel 可能会在 copyincopyout 这两个函数中访问这个内存地址,而 kernel 内是无法像用户程序那样走 page fault handler 来 lazy allocation 的,所以我们必须在 copyincopyout 函数内也实现“访问用户程序传来的内存地址时做 lazy allocation”的逻辑:

copyout
这里 copyout 通过 walkaddr 来将 va 借助 user page table 来翻译得到 pa,但由于我们采用了 lazy allocation 机制,所以这里可能无法找到 PTE 映射,所以,当没有找到 PTE 映射时,我们需要立刻为其分配物理内存并修改 user page table,这也是上图红方框内代码的逻辑。对于 copyin 函数,所做的修改类似:

copyin
至此,我们完成了 lazy allocation,测试如下:

运行 lazytests:
lazytests
运行 usertests:
usertests

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1430360.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端面试拼图-数据结构与算法

摘要&#xff1a;总结一些前端算法题&#xff0c;持续更新&#xff01; 一、数据结构与算法 时间复杂度-程序执行时需要的计算量&#xff08;CPU&#xff09; 空间复杂度-程序执行时需要的内存空间 前端开发&#xff1a;重时间&#xff0c;轻空间 1.把一个数组旋转k步 arr…

CSS的复合选择器

一,什么是复合选择器 常用的复合选择器有:后代选择器、子选择器、并集选择器和伪类选择器。 二,后代选择器(用空格)(重点) 后代选择器也称包含选择器,可以选择父元素里面的子元素。写法就是外层标签在前面,内层标签写后面,中间要有空格隔开。当标签发生嵌套时,内层…

PostgreSQL 也很强大,为何在中国大陆,MySQL 成为主流,PostgreSQL 屈居二线呢?

问题&#xff1a; PostgreSQL 也很强大&#xff0c;为何在中国大陆&#xff0c;MySQL 成为主流&#xff0c;PostgreSQL 屈居二线呢&#xff1f;PostgreSQL 能否替代 MySQL&#xff1f; 当我们讨论为何 MySQL 在中国大陆成为主流而 PostgreSQL 屈居二线时&#xff0c; 我们其实…

servlet会话API

servlet会话API 您可以使用servlet会话API中定义的类和接口来创建和管理用户会话。servlet会话API提供的用于创建和管理用户会话的各种接口有javax.servlet.http.HttpSession、javax.servlet.httpSessionListener和javax.servlet.http.HttpSessionBindingListener和javax.serv…

unity角色触摸转向

1、挂载脚本到角色的父物体A上 2 、以屏幕左边的触摸为移动&#xff0c;右边为转向操作 3、加载角色时&#xff0c;将角色的父物体设置为A&#xff0c;须将角色的位置和角度置0 using System; using System.Collections; using System.Collections.Generic; using UnityEngin…

OTG -- STM32 OTG驱动代码下载及简述(三)

目录 前沿 1 STM32 OTG标准库的获取 2 设备模式代码匹配开发板 2.1 OTG FS全速代码修改 2.2 OTG HS代码修改 2.2.1 OTG HS外部高速PHY运行在高速模式代码修改 2.2.2 OTG HS外部高速PHY运行在全速模式代码修改 2.2.3 OTG HS内部全速PHY运行在全速模式代码修改 前沿 前面…

linux 组建和卸载raid1、raid0详细操作

组raid的最好是相同容量和型号的硬盘&#xff0c;否则会有木桶效应 linux下组raid有很多细节 一、安装raid软件 deb包 apt-get install mdadm或dnf包 dnf install mdadm二、组raid1-镜像&#xff0c;组raid0-并列 raid1和raid0只有在madam命令时一点点不同&#xff0c;其他…

python 下载腾讯在线文档

import requests""" 1. 手动到chrome获取下载请求 2. 获取excel的动态id 3. 拼出excel的下载链接 4. 下载 """class Excel:def __init__(self):self.cookie_string ""self.headers {"authority": "docs.qq.com"…

中缀转后缀

概念 什么是后缀表达式&#xff1f; 后缀表达式&#xff0c;其实就是一个中缀表达式 AOB > ABO &#xff08;A、B是式子、O 为运算符&#xff09;&#xff0c;将运算符向后放 中转后举例 中缀表达式&#xff1a;&#xff08;a b&#xff09;* c - (d / c) 首先&#xff…

CANoe学习笔记—关于cfg工程界面的分类

创建一个工程过程中&#xff0c;如何规划好界面设置&#xff0c;对于后续使用和维护起到了非常好的作用。故整理下 1&#xff1a;首先规划好大致结构图 CANoe中工程的规划Trace界面ConfigurationBuildInToolControlDiagnosticPanel预留 当然&#xff1a;此格式不是固定的&…

高级FPGA开发之基础协议PCIe

基础协议之PCIe部分 一、TLP包的包头 在PCIe的系统中&#xff0c;tlp包的包头的结构有许多部分是相似的&#xff0c;通过掌握这些常规的包头&#xff0c;能帮助理解在PCIe总线上各个设备之间如何进行数据的收发。 通用的字段 通用字段作用Fmt决定了包头是3DW还是3DW&#xff…

20240203在WIN10下配置stable-diffusion-webui.git

20240203在WIN10下配置stable-diffusion-webui.git 2024/2/3 11:55 【结论&#xff1a;在WIN10下&#xff0c;生成512x512分辨率的图像&#xff0c;大概需要9秒钟&#xff01;】 【结论&#xff1a;在Ubuntu20.04.6下&#xff0c;生成512x512分辨率的图像&#xff0c;大概需要1…

Unity 图片不改变比例适配屏幕

Unity 图片不改变比例适配屏幕 前言项目场景布置代码编写添加并设置脚本效果 前言 遇到一个要让图片适应相机大小&#xff0c;填满屏幕&#xff0c;但不改变图片比例的需求&#xff0c;记录一下。 项目 场景布置 代码编写 创建AdaptiveImageBackground脚本 using System.C…

Unity项目从built-in升级到URP(包含早期版本和2023版本)

unity不同版本的升级URP的方式不一样&#xff0c;但是大体流程是相似的 首先是加载URP包 Windows -> package manager,在unity registry中找到Universal RP 2023版本&#xff1a; 更早的版本&#xff1a; 创建URP资源和渲染器​​ 有些版本在加载时会自动创建&#…

【全网独创】2024美赛E题33页成品论文+1-4问完整代码数据助攻

E题社区抗灾能力综合评估与决策模型研究 摘要&#xff1a;社区抗灾能力的提升对于灾害风险管理至关重要。本研究基于机器学 习方法&#xff0c;构建了社区抗灾能力预测模型&#xff0c;以评估社区在灾害事件中的表现。首先&#xff0c; 我们采用梯度提升树模型对社区基础设施、…

Node.js 模块化

一、介绍 1.1 什么是模块化与模块 ? 将一个复杂的程序文件依据一定规则&#xff08;规范&#xff09;拆分成多个文件的过程称之为 模块化 其中拆分出的 每个文件就是一个模块 &#xff0c;模块的内部数据是私有的&#xff0c;不过模块可以暴露内部数据以便其他 模块使用 1…

【Java程序设计】【C00240】基于Springboot的班级综合测评管理系统(有论文)

基于Springboot的班级综合测评管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的班级综合测评管理系统 本系统分为学生功能模块、管理员功能模块以及教师功能模块。 管理员功能模块&#xff1a;管理员功能…

windows下安装go

下载golang Go 官网下载地址&#xff1a; https://golang.org/dl/ Go 官方镜像站&#xff08;推荐&#xff09;&#xff1a; https://golang.google.cn/dl/ 选择安装包 验证有没有安装成功 查看 go 环境 说明 &#xff1a; Go1.11 版本之后无需手动配置环境变量&#xff0c…

Vue 环境准备

1.安装vscode https://code.visualstudio.com/ 2.安装开发vue所需插件&#xff1a; Vetur —— 语法高亮、智能感知、Emmet等 包含格式化功能&#xff0c; AltShiftF &#xff08;格式化全文&#xff09;&#xff0c;CtrlK CtrlF&#xff08;格式化选中 代码&#xff0c;两…

【Matplotlib】figure方法之图形的保存

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;matplotlib &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…