虚拟内存管理实习报告

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

虚拟内存管理实习报告

姓名李炜学号**********

日期4月10日

目录

内容一:总体概述 (3)

内容二:任务完成情况 (3)

任务完成列表(Y/N) (3)

具体Exercise的完成情况 (3)

内容三:遇到的困难以及解决方法 (9)

内容四:收获及感想 (9)

内容五:对课程的意见和建议 (9)

内容六:参考文献 (10)

内容一:总体概述

这次实习主要是加入对tlb和虚拟内存的进一步支持,并且实验一下在原理课上学到过的各种替换策略,tlb是为了加速从虚拟地址到物理地址的翻译过程,而虚拟内存更是肩负着提供比实际物理内存更大的虚拟内存的重任,有了虚拟内存,才可以运行比实际内存更大的程序。

内容二:任务完成情况

任务完成列表(Y/N)

具体Exercise的完成情况

TLB异常处理部分:

Exercise 1:

这个文件中和本次实习相关的主要是StartProcess这个函数,在这个函数中,首先打开一个文件,判断这个文件是否是可执行文件,如果是的话,为这个文件开辟一块地址空间来运行一个新线程,之后初始化和这个线程相关的寄存器,初始化完成之后运行这个程序。其中在开辟新的地址空间的时候,为这个地址空间中的page table的每一项进行了初始化。所以在后面对translationEntry增加内容的时候,最好还是在这个初始化过程中加入相应的初始化操作。

在构造可执行文件的空间时,首先读入这个文件的开始部分,即noffH,这个部分包含了文件的magic number(表示是否是可执行文件),文件中代码,数据,栈等各部分的位置、大小等。之后根据这个大小,按照页大小分配内存页数量,初始化page table,将可执行文件的代码段和数据段按照虚存与内存一一对应的方式读入内存中。

(h)

在这个文件中,主要是针对虚拟机整体的操作,其中在构造函数中,首先初始化了寄存器和

内存,这个部分和本次实习没有关系,下面初始化了tlb中的项。开始的时候,我认为对于每个地址空间都应该有自己的tlb,每次切换线(进)程的时候都要同时切换tlb内容,这个方案在nachos这样的虚拟机上实际上时可以实现的,而且tlb的miss可能会比只有一个tlb 要少很多,但是这种情况不符合计算机系统的实际情况,因为对于实际的计算机体系结构来说,tlb是一个硬件不见,每个cpu的核心应该具备一个tlb,因为多超标量等优化机制的存在,线程切换十分频繁,如果每次都要同时按照线程切换tlb,那样代价太大了,tlb本身是用来利用局部性来减少对page table的访问的,如果频繁改变tlb内容开销上太大,得不偿失。

在这个文件中,与本次实习相关的还有raiseexception这个函数,这个函数其实就是针对不同的异常调用相应的处理函数的地方,在处理异常之前要先使得系统进入系统模式运行(之前在用户模式下)。

(h)

这个文件在这次实习中具有十分重要的作用,readMem和writeMem分别是从内存中读和写的函数,它们都需要首先进行虚拟地址到物理地址的转换,如果转换成功则继续读写操作,否则会对因为转换产生的异常进行处理。在translate函数中,首先检查想要读取的内存地址是不是对齐的,之后根据虚拟地址算出相应的虚拟页号和页内偏移(需要转换的其实只是虚拟页号到物理页号,页内偏移在虚拟页中和在物理页中都是相同的)。因为nachos本身只支持tlb或者page table中的一个,所以如果是page table模式的话,那么就在page table中直接取出vpn对应的项,并且取出物理页号,当然其间也要进行有效性检查,如果所需要的物理页是无效的,就会引发page fault异常。如果使用的是tlb模式,则在tlb中遍历查找想要读取的vpn,如果找不到,同样会引发page fault异常。之后的操作就是读出这个物理页的具体地址以及一些其它的检查操作。

对于这个文件来说,只有一个Exceptionhandler函数,用来判断异常的类型和相应的处理方式并且处理异常,对于本次实习来说,其实就是加一个else if判断pagefaultexception异常并处理这个tlb miss。

Exercise 2:

从ExceptionHandler中可以看到对于系统调用的处理方法,就是输出调试信息,并且停止用户进程,对于TLB miss来说,开始的时候我仍然使用了PageFaultException,因为在translate 文件中如果出现tlb miss会返回PageFaultException,也就是说在handler中首先判断产生的是PageFaultException,判断完之后,我感到很茫然,因为除了需要知道是何种异常外,还必须知道引发这个寻址异常的具体地址是什么,这样才能从page table中调入这个页,去哪里得知这个信息呢?重新去看translate中的读写内存的两个函数,可以看到translate函数返回异常,那么就会调用RaiseException这个函数,而我们可以看到引发异常的那个地址也被当做参数传了进去,在这个函数中,和这个我们需要的地址有关的就是把这个地址写到了一个寄存器中,因为寄存器是machine中的属性,也就是说不管是用户进程还是系统进程都共享相同的寄存器,这样我们就知道可以在exception handler中通过读取寄存器信息来得到那个引发异常的地址了。那么是哪个寄存器呢?从raiseException中可以看到是BadVAddrReg,这个是一个宏,对应着39号寄存器。这样,在ExceptionHandler中,我首先

通过machine的读取寄存器的方法读出BadVAddrReg寄存器中的内容,有了这个地址就可以开始具体的替换过程了,对于替换的方法,我首先实验了通过hit次数多少来决定去除哪一个entry的方法,因为其中许多操作都涉及machine中的信息,所以我把这个处理函数放在了machine中,这个函数接受地址作为参数,学习translate中的方法,首先通过address计算获得vpn和offset,其实后来发现offset用处不大,只是在输出哪个物理地址时有帮助,有了vpn也就知道了哪个页要被换进,问题就是要找到一个tlb项来换出,对于这个目标来说,也很简单,只要通过遍历tlb表项,找到hit最小的一项,如果有valid为false的项,那么可以直接把这个项作为应该被换出的项即可,之后把这个tlb项写回到page table中,并且把vpn号page table中的项调入这个应该被换出的项所在的位置。之后还需要做些tlb项的初始化工作,把这个项的hit置为1(如果置成0的话可能会造成震荡,这一点是我在调试程序的时候,发现的),valid置为TRUE,为了看哪个地址引发了异常,我还让它输出了对应的物理地址。当然还要维护这个hit值,也就是说,在translate中每次tlb项被找到,就使相应的hit值加一。

但是再后来的测试阶段我发现matmult这个算矩阵乘法的程序会产生真正的pagefault(内存不足),这样就有必要区分tlb miss和page fault了,于是我在machine.h中定义了新的异常类型叫TLBMissException,并且在exceptionHandler中添加了对这种类型的处理。

Exercise 3:

已经有了上一个exercise的基础,其实这个exercise也就不难了,我首先选择了使用aging 算法(因为体系大作业曾经实现过,觉得不难),我通过定义宏GROWOLD使得tlb项的age 右移一位,通过REFEREDTO使得age右移一位并且首位或上1,每次tlb项被使用时,就对它REFEREDTO,而在Exceptionhandler中如果不是要找的项,就先对它GROWOLD,这样较近时间被使用的tlb项就不会很快被换出(找的时候直接找age最小的就可以)。说起来比较简单,但是实际编写的过程中,发现在sort这个程序的测试中出现了震荡现象,经过仔细检查发现是因为age在translationEntry中被我定义为了int,但是实际上必须被定义成unsigned int,在找age最小的时候也需要使用unsigned int类型。

之后听同学说lru实现起来比较简单,只需要通过stats->totalTick就可以知道最近被访问的时间了,于是我在之前应该REFEREDTO的地方把lastUsedTime赋成stats->totalTick,比较的时候同样找lastUsedTime最小的项。由于实现起来差不多,所以就不多说了。

测试的时候我主要跑了halt,sort,matmult三个程序,halt是用来验证pageTable中的项可以被换入的正确性的,对性能比较上基本没有意义。而在测试sort时,aging算法和lru竟然产生了相同的miss次数,在tlb最多为8的时候,内存为1024页的时候,都产生了8678次miss,改变一些参数仍然相同,于是我只好继续通过matmult来测试。但是matmult在测试时会产生很大的问题,tlb中竟然出现了多次相同的项且valid都是1,我查了很长时间程序都不知道哪里错了,后来看matmult程序本身,发现注释说这个程序会造成内存溢出,于是我明白了,因为开始的时候我没有区别tlb miss和page fault,所以其实是引发了真正的page fault,之后像之前说的,我首先扩大了内存页数从128变到1024,之后区别page fault 和tlb miss,这样之后测试aging和lru的miss次数,结果令我大跌眼睛,aging miss发生了8647次,而lru却只发生了5722次,原本一位aging会更高级的,结果却是原理更加简单的lru的miss次数更少。

相关文档
最新文档