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

MIT6.S081 LAB page tables (2024)

page tables

文章目录

  • page tables
    • Inspect a user-process page table (easy)
    • Speed up system calls (easy)
    • Print a page table (easy)
    • Use superpages (moderate/hard)

HOME MIT 6.S081

Inspect a user-process page table (easy)

题目
在这里插入图片描述

这个好像直接现成实现好了

Speed up system calls (easy)

题目

在这里插入图片描述
大概的含义就是,有些系统调用其实只是想要拿到系统中的信息,所以想到了将这部分数据放在用户可以访问的位置,这样就不需要再进行系统调用,从而加速了系统调用的时间。
思路

因为这是每个进程可能特有的信息,所以应该添加到进程的属性上,修改proc的定义,然后为它在Trapframe下面分配一页(虚拟地址),所以先给这个usyscall分配一个物理页面,然后将这个物理地址与USYSCALL在页表上建立映射。然后在进程销毁的时候,释放掉这个页,并且在页表上释放对这个页的映射。

实现

先分配一个内存页,用于存储usyscall。
在这里插入图片描述
在页表上建立虚拟地址到这个内存页的映射
在这里插入图片描述
释放掉分配到的物理页
在这里插入图片描述
释放掉在页表上映射的内存空间
在这里插入图片描述

Print a page table (easy)

题目

在这里插入图片描述

题目大概说的就是将页表中指向的所有分配了物理地址的部分全都按照这种形式输出出来,具体的效果应该类似于上图的下半部分,一级一级的输出页号,然后pte的值以及指向的物理地址。
实现

首先知道每级页表大小都是4096B,页表项都是8B,所以有4096 / 8 = 512个页表项,所以只要去递归遍历每级页表的所有页表项,如果出现有效的指向下一级就往下递归,需要注意的是,下一级要知道上一级查过来的虚拟地址,所以需要一个baseP来还原每个页表项对应的虚拟地址。
在这里插入图片描述
实验结果
跟所给结果不一样的是打印的时候没有去除前导0,但实际内容相同
在这里插入图片描述

Use superpages (moderate/hard)

题目
在这里插入图片描述
题目的大概意思就是xv6中原来每个页面只支持映射4096B的数据,但是如果一个进程需要很多页的时候页面分配查找需要非常多次,从而会导致效率不高。所以现在让我们修改其中的代码实现超级页(一页2MB)的功能,也就是当需要的空间很大的时候可以一次分配一个超级页。

思路

先分析测试的代码,如下图,superpg_test会先通过sbrk再给进程分配Nbyte的空间(超过一个超级页的大小),然后从SUPERPGROUNDUP(end)的地方(这个其实已经是对后面一个大坑的提示了)开始进入supercheck进行测试,测试的逻辑是读写检查是不是分配到了超级页,如果不是超级页的话页面发生变化pte会发生改变。
在这里插入图片描述
实现

先不管后面fork的测试部分,先完成fork前的测试点。

这里可以注意到超级页的大小刚好是 2 21 B = 2 9 × 2 12 B 2^{21}B = 2^{9} \times 2^{12}B 221B=29×212B,而xv6的多级页表结构如下图。所以超级页分配的时候只需要让分到超级页的虚拟地址的L1指向的pte直接指向物理地址(而不是指向下一级页表)就ok了,这样连续的 2 21 B 2^{21}B 221B的虚拟地址能用相同的pte找到映射的物理地址。
在这里插入图片描述
因此,首先要能分配到一个 2 21 B 2^{21}B 221B大小的连续内存空间。关于内存空闲空间分配的代码在kernel/kalloc.c文件中,我们添加如下代码(左侧绿色条的就是修改或新增的代码):

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样就能通过superKalloc来分配一个超级页大小的连续内存空间了。接下来就是看sbrk进入到系统调用做了些什么,发现调用链是kernel/sys_proc.c:sys_sbrk->kernel/proc.c:growproc->kernel/vm.c:uvmalloc 。这部分代码原先的逻辑就是给进程分配更多的PAGE,我们需要改的是检查要是一次请求分配的虚拟地址空间足够大而且是能够作为超级页的虚拟地址始址的时候那就分配一个超级页,代码实现如下图。
在这里插入图片描述
当能分配超级页的时候就调用mapSuperPage将分配的超级页记录到页表上,也就是在二级页表项上增加PTE_SPUER的标记(可以对着上面的多级页表结构理解)。
在这里插入图片描述
在这里插入图片描述
这样我们就在页表上标记了哪个是超级页,还需要修改的是如果读到为PTE_SPUER的页表项后,就不用再读第三级页表了,所以去修改kernel/vm.c:walk
在这里插入图片描述
现在成功将超级页记录到了页表,而且能够读写其中的数据。有始有终,所以还需要修改一下释放的页表的代码(kernel/vm.c:uvmunmap),理解了前面的这个释放应该就不难。

在这里插入图片描述
做到这我们就可以通过fork前面的测试,但是fork后的测试用例还不能通过。这是因为,fork创建的子进程的时候会拷贝原来的进程的数据到新的内存空间,然后创建一个新的页表来做虚拟地址到物理地址的映射(kernel/vm.c:uvmcopy)。问题就出在拷贝到新的内存空间的时候,要改的就是将原来的超级页数据也拷贝到超级页上。所以做如下修改:
在这里插入图片描述
至此就可以成功运行测试用例,看到如下结果
在这里插入图片描述


http://www.kler.cn/news/361025.html

相关文章:

  • C++ 游戏开发:从基础到进阶
  • 2025秋招八股文--网络原理篇
  • React 基础阶段学习计划
  • 点云数据介绍
  • [论文笔记]RA-DIT: RETRIEVAL-AUGMENTED DUAL INSTRUCTION TUNING
  • Golang | Leetcode Golang题解之第497题非重叠矩形中的随机点
  • Python程序设计 内置函数 日志模块
  • eIQ笔记(UI介绍+Loss曲线+OpenART例程)
  • linux更改系统时间
  • 基于基于MATLAB红外和可见光图像融合算法研究
  • 【分布式微服务云原生】《微服务架构下的服务治理探秘》
  • 从外行人的角度解释1Bit的模型,是怎样改变世界的
  • Qt编写的modbus模拟器/支持网络和串口以及websocket/支持网络rtu
  • Standard_Matrix
  • 异步优化看板查询接口,从29s优化至2.8s
  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
  • Tcp协议讲解与守护进程
  • 第二十八篇:TCP协议概述,TCP系列二
  • 华为OD机试2024年真题(基站维修工程师)
  • 【二】企业级JavaScript开发之代码编辑器