一、实验目的

在上一章PA3-2中,我们实现了分段机制,将48位的虚拟地址vaddr转换成了laddr。为什么不是paddr呢?这就要说到这一章要完成的东西:**分页机制 **。

从80386开始,计算机又提供了一种全新的存储管理方式,那就是分页机制。在分页机制下,每一个进程都拥有独立的存储空间。同时,每一个进程独立的存储空间又具有相同的地址划分方式。此时,线性地址就需要通过进一步的转换,才能获得最终要访问的物理地址。PA3-3中我们将要实现对NEMU分页机制的模拟。

二、实验任务与步骤

老规矩,我们先来看为啥需要分页机制。分段机制的意义在于把混乱的内存管理划分出层次,把代码、数据、堆栈都划分好。到这里感觉对内存的管理已经很完善了——但实际上这还不够。主存太小了!当有多个进程需要运行的时候就显得十分吃力。

我们现在运行NEMU时,要运行在上面的“软件”就只有两个:kernel和一个testcase。我们知道Kernel占多少字节,通过修改testcase/Makefile设置-Ttext为0x100000来避免内存区域的冲突。但如果同时存在多个testcase要同时运行,且装载顺序在运行时动态确定,就没办法在编译时就确定各个进程内存起始地址,管理起来非常麻烦。到这里,我们可以总结分段机制现在面临的问题:

  1. 物理内存大小的限制
  2. 多进程并行

所以我们引入分页机制。我们来看看分页、Cache都有的一个逻辑如下:

要解决上面的两个问题,我们需要解决几个要点:

  • 寻址空间无法突破物理内存空间的限制?

    • 上层和下层存储器按照同样的大小划分成一个个“单元”
    • 解决上下层存储器“单元”之间的映射问题
  • 多个进程并行运行,同时占用内存时如何分配?
    • 各个进程在运行前不需要关心运行时的内存分配情况
    • 各个进程运行时所占用的物理内存“单元”不要起冲突(除非指明要共享)

要点解释完了,我们来看看是具体流程

  • 首先,内存不是不足嘛,我们就想象每个进程的4GB空间在运行时都存储在硬盘上,硬盘够大了吧!

  • 实际上我们并没有这样做(硬盘的读写太慢太慢)。我们要引入一个“虚拟地址空间”的概念:假想每一个进程都有4GB的空间,即每一个进程都以为自己是独享内存的。这样的话,程序员无需考虑运行时内存的分配情况,只需针对虚拟地址空间进行编译就可以了。

  • 然后,对于一个个虚拟地址空间,我们要做的就是建立其虚拟地址空间和物理地址空间的映射

  • 到了这一步,你可能会想:哎呀这一片那一片这不全乱套啦!这么多进程的页混杂在一起...没关系,我们如果访问到缺失的页,这时候再拿进来就行了:

  • 我们的操作系统维护各个进程的虚拟页和物理页之间的映射关系,每个进程都有一个它自己的页表:

  • 页表项的结构如下,页表在内存中存储为一个页表项的数组。

    我们约定一个页为4KB = 212B,即32位线性地址中,前20bit是页索引,侯12bit是页内地址。那么我们足足有220个页表项!一个页表达到了4MB!在内存中遍历连续的4MB的数组空间很难,所以我们把它又划成了二级页表。简单说就是前面的20位页号被拆成了两个10位,前10bit是页目录索引,后10bit是页索引。

  • 那么现在我们要做的地址转换操作如下:

好,具体流程我们也搞懂了,现在来看看NEMU是如何具体实现的:

  1. include/config.h头文件中定义宏IA32_PAGEmake clean

  2. 修改kernel和testcase中Makefile的链接选项

    • 修改kernel/Makefile中的链接选项:

      这里给出我自己的理解:

      我们知道,kernel.img文件是依靠我们实际机器来转载到NEMU的内存中的。它的物理上的被装载位置还是处于hw_mem+0x30000的位置,但是,它的文件内容却因为链接选项的改变而改变了:

      原本kernel代码的起始指令地址是0x30000,现在是0xc0030000。

      kernel的指令从0xc0030000一路向下,0xc0030001,0xc0030002……

      而kernel被我们实际机器装载进去NEMU的内存后,kernel的执行就靠NEMU的环境了。0xc0030000开始的指令取指、存取操作数都需要用到你自己实现的访存函数,它会经过分段机制转换成线性地址,再通过分页机制转成物理地址。

      #define va_to_pa(x) (x - KOFFSET)这个宏的意义在于:

      我们知道kernel的指令段的地址是从0xc0030000开始(虽然装载在NEMU的0x30000),但我们要装载GDT的首地址到GDTR的话,虽然gdtdesc在NEMU的位置实际上是处于hw_mem + 0x30000后面某处的,但根据链接给它排的序,它字面上是在0xc0030000的后面!如果我们直接就把gdtdesc的地址用lgdt装进GDTR,那么GDTR的值就变成一个大于0xc0030000的值。所以我们用这个宏耍一点小手段,把GDTR的值变成和实际上的地址相符,即处于hw_mem + 0x30000后面某处。(init_page()前没有kernel页表

    • 修改testcase/Makefile中的链接选项:

      这个举动的意义在于让你的testcase的ELF格式更加符合Linux规定(即原版),就像上图。在NEMU环境下kernel对其装载还是用你实现的mov,但现在mov的访存已经有了分页操作,没改之前是直接根据程序头表的0x100000装载到0x100000,现在即使是从0x80488000开始,也能通过有了分页机制的访存函数来将它转换成正确的属于NEMU内存的装载地址中去。

  3. 在NEMU中添加分页相关器件支持

    • 添加CR3寄存器,实现对页表基地址(物理页框号)的存储
    • 添加CR0PG位,实现开启/关闭分页机制
  4. 实现从线性地址到物理地址的转换,修改laddr_read()laddr_write(),适时调用page_translate()函数进行地址翻译(page_translate()定义在nemu/src/memory/mmu/page.c);

  5. 修改Kernel的loader(),使用mm_malloc来完成对用户进程空间的分配;

    为了减轻大家的负担, 我们已经为大家准备了一个内存分配的接口函数mm_malloc()其函数原型为:

    uint32_t mm_malloc(uint32_t va, int len);

    它的功能是为用户进程分配一段以虚拟地址va开始,长度为len的连续的物理内存区间,并填写为用户进程准备的页目录和页表,然后返回这一段物理内存区间的首地址。由于mm_malloc()的实现和操作系统实验有关,我们没有提供 mm_malloc() 函数的源代码,而是提供了相应的目标文件mm_malloc.oMakefile中已经设置好相应的链接命令了, 你可以在loader()函数中直接调用它, 完成上述内存分配的功能。

  6. 通过make test_pa-3-3执行并通过各测试用例。

自己的一点小记:

首先,kernel的代码,用户程序是直接执行不了的。

其次,kernel的代码取指啥的会调用自己写的读写函数,会经过分页机制转换,页是取kernel页表。

还有,kernel页表在init_page()建立前,需要用到那个耍赖的宏定义,直接减去koffset。

三、思考题

1.Kernel的虚拟页和物理页的映射关系是什么?请画图说明;

2.以某一个测试用例为例,画图说明用户进程的虚拟页和物理页间映射关系又是怎样的?Kernel映射为哪一段?你可以在loader()中通过Log()输出mm_malloc的结果来查看映射关系,并结合init_mm()中的代码绘出内核映射关系。




3.“在Kernel完成页表初始化前,程序无法访问全局变量”这一表述是否正确?在init_page()里面我们对全局变量进行了怎样的处理?

这句话是错误的。如果PE位和PG位没有开启,那么就是没有进入保护模式,kernel是可以直接通过逻辑地址访问全局变量。

我们在init_page()中对全局变量的处理是使用了align_to_page进行对齐。

NEMU PA 3-3 实验报告的更多相关文章

  1. ucoreOS_lab3 实验报告

    所有的实验报告将会在 Github 同步更新,更多内容请移步至Github:https://github.com/AngelKitty/review_the_national_post-graduat ...

  2. ucoreOS_lab2 实验报告

    所有的实验报告将会在 Github 同步更新,更多内容请移步至Github:https://github.com/AngelKitty/review_the_national_post-graduat ...

  3. JAVA实验报告及第七周总结

    JAVA第六周作业 实验报告五 第一题 1.设计一个类层次,定义一个抽象类--形状,其中包括有求形状的面积的抽象方法. 继承该抽象类定义三角型.矩形.圆. 分别创建一个三角形.矩形.圆存对象,将各类图 ...

  4. 第五次java实验报告

    Java实验报告 班级 计科二班 学号 20188437 姓名 何磊 完成时间2019/10/10 评分等级 实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. 实 ...

  5. 第七周总结&第五次实验报告

    学习总结 这周我们加深了对抽象类与接口的学习,获得的知识点也比上周多了许多,抽象类与接口很相似,就比如别人还没有做完的是交给你来做,而他那些样式都做好了,你只需要完善即可 但也有不同点. 区别点 抽象 ...

  6. 第七周课程总结 & 实验报告(五)

    第七周课程总结 一.抽象类与接口的应用 1.实例化 2.实际应用 ---模板设计(抽象类) ---制定标准(接口) 3.设计模式 ---工厂设计 ---代理设计 ---适配器设计 二.抽象类与接口之间 ...

  7. 第七周&实验报告五

    实验四 类的继承 •实验目的 •理解抽象类与接口的使用: •了解包的作用,掌握包的设计方法. •实验要求 •掌握使用抽象类的方法. •掌握使用系统接口的技术和创建自定义接口的方法. •了解 Java ...

  8. 2019JAVA第五次实验报告

    Java实验报告 班级 计科二班 学号 20188442 姓名 吴怡君 完成时间2019/10/11 评分等级 实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. ...

  9. 实验报告5&第七周课程总结

    实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法. 实验要求 掌握使用抽象类的方法. 掌握使用系统接口的技术和创建自定义接口的方法. 了解 Java 系统包的结构. ...

  10. 北京电子科技学院(BESTI)实验报告5

    北京电子科技学院(BESTI)实验报告5 课程: 信息安全系统设计基础 班级:1452.1453 姓名:(按贡献大小排名) 郑凯杰.周恩德 学号:(按贡献大小排名) 20145314.20145217 ...

随机推荐

  1. /etc/profile,/etc/bashrc,~/.profile,~/.bashrc 的区别及使用

    转载请注明出处: /etc/profile  为系统的全局环境变量设置,此文件为系统的每个用户设置环境信息    /etc/bashrc 为每一个运行bash shell的用户执行此文件.当bash ...

  2. spring-transaction源码分析(5)TransactionInterceptor事务拦截逻辑

    spring-tx的事务拦截逻辑在TransactionInterceptor类,本文将详细分析其实现方式. 事务拦截器TransactionInterceptor spring-tx的事务拦截逻辑在 ...

  3. SV 接口中的clocking

    接口 module可以例化模块,可以例化接口 接口不能例化模块 采样和数据驱动 时钟驱动数据,数据会有延迟,RTL仿真的时候,不会仿真出这个延时;RTL仿真的时候,不会仿真出寄存器的延时;只有在门级仿 ...

  4. 02-python简介

    python简介 python认知 1.python简介 89年开发的语言,创始人范罗苏姆(Guido van Rossum),别称:龟叔(Guido). python具有非常多并且强大的第三方库,使 ...

  5. 你老了,别搞IT了……

    你老了,别搞IT了-- [来源]

  6. 【TouchGFX 】使用 CubeMX 创建 TouchGFX 工程时 LCD 死活不显示

    生成的代码死活无法让LCD显示,经两个晚上的分析验证是LTDC_CLK引脚速度设置为低速导致,经测试中速.高速.超高速都正常,真是冤,聊以此以示纪念

  7. Qt5.9 UI设计(五)——将Tabwidget与treeWidget相互关联

    前言 前面一章介绍了ControlTabWidget ControlTreeWidget maintitlebar 三个子页面同时布局到 mainwindow 的方法,本章介绍如何将ControlTr ...

  8. K8S Only IPV6的创建过程之二 完整版

    K8S Only IPV6的创建过程之二 完整版 整体过程 1. 阿里云新增一台虚拟机, 开通IPV6.与数据库,redis实现物理隔离. 并且进行环境基本处理,安装kubeadm等组件. 2. ku ...

  9. 各种数据库shell一键登录的方法

    各种数据库shell一键登录的方法 一个小场景 想通过shell 直接执行一些内容. 然后发现通过shell就可以. 所以这里总结一下 1. Oracle export ORACLE_HOME=/u0 ...

  10. [转帖]java -D参数设置系统属性无效问题及解决

    https://www.jb51.net/article/271236.htm   这篇文章主要介绍了java -D参数设置系统属性无效问题及解决方案,具有很好的参考价值,希望对大家有所帮助.如有错误 ...