《虚拟内存管理实习报告》由会员分享,可在线阅读,更多相关《虚拟内存管理实习报告(10页珍藏版)》请在金锄头文库上搜索。
1、虚拟内存管理实习报告姓名 李炜 学号 1100012810日期 4 月 10 日2目录内容一:总体概述 .3内容二:任务完成情况 .3任务完成列表(Y/N) .3具体 Exercise 的完成情况 .3内容三:遇到的困难以及解决方法 .4内容四:收获及感想 .5内容五:对课程的意见和建议 .5内容六:参考文献 .53内容一:总体概述这次实习主要是加入对 tlb 和虚拟内存的进一步支持,并且实验一下在原理课上学到过的各种替换策略,tlb 是为了加速从虚拟地址到物理地址的翻译过程,而虚拟内存更是肩负着提供比实际物理内存更大的虚拟内存的重任,有了虚拟内存,才可以运行比实际内存更大的程序。内容二:任务
2、完成情况任务完成列表(Y/N )Exercise1 Exercise2 Exercise3TLB 异常处理Y Y Y分页式内存管理Y Y YLazy-loadingY倒排页表 Y具体 Exercise 的完成情况TLB 异常处理部分:Exercise 1:Progtest.cc这个文件中和本次实习相关的主要是 StartProcess 这个函数,在这个函数中,首先打开一个文件,判断这个文件是否是可执行文件,如果是的话,为这个文件开辟一块地址空间来运行一个新线程,之后初始化和这个线程相关的寄存器,初始化完成之后运行这个程序。其中在开辟新的地址空间的时候,为这个地址空间中的 page table
3、的每一项进行了初始化。所以在后面对 translationEntry 增加内容的时候,最好还是在这个初始化过程中加入相应的初始化操作。在构造可执行文件的空间时,首先读入这个文件的开始部分,即 noffH,这个部分包含了文件的 magic number(表示是否是可执行文件) ,文件中代码,数据,栈等各部分的位置、大小等。之后根据这个大小,按照页大小分配内存页数量,初始化 page table,将可执行文件的代码段和数据段按照虚存与内存一一对应的方式读入内存中。Machine.cc(h)在这个文件中,主要是针对虚拟机整体的操作,其中在构造函数中,首先初始化了寄存器4和内存,这个部分和本次实习没有
4、关系,下面初始化了 tlb 中的项。开始的时候,我认为对于每个地址空间都应该有自己的 tlb,每次切换线(进)程的时候都要同时切换 tlb 内容,这个方案在 nachos 这样的虚拟机上实际上时可以实现的,而且 tlb 的 miss 可能会比只有一个 tlb 要少很多,但是这种情况不符合计算机系统的实际情况,因为对于实际的计算机体系结构来说,tlb 是一个硬件不见,每个 cpu 的核心应该具备一个 tlb,因为多超标量等优化机制的存在,线程切换十分频繁,如果每次都要同时按照线程切换 tlb,那样代价太大了,tlb 本身是用来利用局部性来减少对 page table 的访问的,如果频繁改变 tl
5、b 内容开销上太大,得不偿失。在这个文件中,与本次实习相关的还有 raiseexception 这个函数,这个函数其实就是针对不同的异常调用相应的处理函数的地方,在处理异常之前要先使得系统进入系统模式运行(之前在用户模式下) 。Translate.cc(h)这个文件在这次实习中具有十分重要的作用,readMem 和 writeMem 分别是从内存中读和写的函数,它们都需要首先进行虚拟地址到物理地址的转换,如果转换成功则继续读写操作,否则会对因为转换产生的异常进行处理。在 translate 函数中,首先检查想要读取的内存地址是不是对齐的,之后根据虚拟地址算出相应的虚拟页号和页内偏移(需要转换的
6、其实只是虚拟页号到物理页号,页内偏移在虚拟页中和在物理页中都是相同的) 。因为nachos 本身只支持 tlb 或者 page table 中的一个,所以如果是 page table 模式的话,那么就在 page table 中直接取出 vpn 对应的项,并且取出物理页号,当然其间也要进行有效性检查,如果所需要的物理页是无效的,就会引发 page fault 异常。如果使用的是 tlb 模式,则在 tlb 中遍历查找想要读取的 vpn,如果找不到,同样会引发 page fault 异常。之后的操作就是读出这个物理页的具体地址以及一些其它的检查操作。Exception.cc对于这个文件来说,只有
7、一个 Exceptionhandler 函数,用来判断异常的类型和相应的处理方式并且处理异常,对于本次实习来说,其实就是加一个 else if 判断 pagefaultexception 异常并处理这个 tlb miss。Exercise 2:从 ExceptionHandler 中可以看到对于系统调用的处理方法,就是输出调试信息,并且停止用户进程,对于 TLB miss 来说,开始的时候我仍然使用了 PageFaultException,因为在translate 文件中如果出现 tlb miss 会返回 PageFaultException,也就是说在 handler 中首先判断产生的是 P
8、ageFaultException,判断完之后,我感到很茫然,因为除了需要知道是何种异常外,还必须知道引发这个寻址异常的具体地址是什么,这样才能从 page table 中调入这个页,去哪里得知这个信息呢?重新去看 translate 中的读写内存的两个函数,可以看到translate 函数返回异常,那么就会调用 RaiseException 这个函数,而我们可以看到引发异常的那个地址也被当做参数传了进去,在这个函数中,和这个我们需要的地址有关的就是把这个地址写到了一个寄存器中,因为寄存器是 machine 中的属性,也就是说不管是用户进程还是系统进程都共享相同的寄存器,这样我们就知道可以在
9、exception handler 中通过读取寄存器信息来得到那个引发异常的地址了。那么是哪个寄存器呢?从 raiseException 中可以看到是 BadVAddrReg,这个是一个宏,对应着 39 号寄存器。这样,在 ExceptionHandler5中,我首先通过 machine 的读取寄存器的方法读出 BadVAddrReg 寄存器中的内容,有了这个地址就可以开始具体的替换过程了,对于替换的方法,我首先实验了通过 hit 次数多少来决定去除哪一个 entry 的方法,因为其中许多操作都涉及 machine 中的信息,所以我把这个处理函数放在了 machine 中,这个函数接受地址作为
10、参数,学习 translate 中的方法,首先通过 address 计算获得 vpn 和 offset,其实后来发现 offset 用处不大,只是在输出哪个物理地址时有帮助,有了 vpn 也就知道了哪个页要被换进,问题就是要找到一个 tlb 项来换出,对于这个目标来说,也很简单,只要通过遍历 tlb 表项,找到 hit 最小的一项,如果有 valid 为 false 的项,那么可以直接把这个项作为应该被换出的项即可,之后把这个 tlb 项写回到 page table 中,并且把 vpn 号 page table 中的项调入这个应该被换出的项所在的位置。之后还需要做些 tlb 项的初始化工作,把
11、这个项的 hit 置为 1(如果置成 0 的话可能会造成震荡,这一点是我在调试程序的时候,发现的) ,valid 置为 TRUE,为了看哪个地址引发了异常,我还让它输出了对应的物理地址。当然还要维护这个 hit 值,也就是说,在 translate中每次 tlb 项被找到,就使相应的 hit 值加一。但是再后来的测试阶段我发现 matmult 这个算矩阵乘法的程序会产生真正的 pagefault(内存不足) ,这样就有必要区分 tlb miss 和 page fault 了,于是我在 machine.h 中定义了新的异常类型叫 TLBMissException,并且在 exceptionHan
12、dler 中添加了对这种类型的处理。Exercise 3:已经有了上一个 exercise 的基础,其实这个 exercise 也就不难了,我首先选择了使用 aging算法(因为体系大作业曾经实现过,觉得不难) ,我通过定义宏 GROWOLD 使得 tlb 项的age 右移一位,通过 REFEREDTO 使得 age 右移一位并且首位或上 1,每次 tlb 项被使用时,就对它 REFEREDTO,而在 Exceptionhandler 中如果不是要找的项,就先对它 GROWOLD,这样较近时间被使用的 tlb 项就不会很快被换出(找的时候直接找 age 最小的就可以) 。说起来比较简单,但是实
13、际编写的过程中,发现在 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,我查了很长时间程序都不知