Nachos虚存
一、概述
本实验牵涉到Nachos虚存子系统的部分实现,也是第一次用到Nachos的虚拟机。测试代码是一组覆盖了绝大部分虚存空间的数组操作,该虚存空间被映射到20个物理页中。
地址转换和页表结构已给出。本实验的目的是要实现缺页处理程序,这需要在适当的时候将某些页面替换出/入。为了减少缺页和将页面从内存淘汰到磁盘的次数,要求你实现五种页面替换算法。
二、准备
素材:
本实验的源代码是/home/nachos/mp3.tar文件。复制到本地目录后解包,你要在userprog子目录下工作,当然也需阅读文件filesys/filesys.h,filesys/openfile.h,machine/translate.h,machine/timer.h,和bin/noff.h。本实验你需修改文件memmanager.h和memmanager.cpp。
下面是一些相关的细节问题。
结构:
大家都知道,每个地址空间都有相应的页表,页表中的每一项称为页表条目。在本实验中,我们会牵涉到其中的三个主要字段:USE、DIRTY和VALID,它们在machine/translate.h中有详细描述。
AddrSpace结构包含了Nachos进程地址空间的所有信息:页表、页表长度等,以及操作地址空间的函数。当创建了一个新的进程时,该结构也就随之产生并初始化。所提供的代码已实现了页面调度机制,在该机制中,仅在一个执行进程访问页面时,才将它从可执行的源文件中读入物理内存。所以,在进程刚创建时,页表中的所有条目都是初始化为无效的(所有页表条目的有效位都置为false)。然而,访问这样的页面(不属于任何程序段)一般来说是不合法的。当初始化一个页表时,要生成一个报告,该报告说明哪些页面的访问是合法的,而哪些页面的访问是不合法的(Legal字段)。每个可执行程序都以一个头开始,它指定程序中所有程序段的虚存范围。
若想得到更多信息,请阅读AddrSpace::AddrSpace()和noff.h中的相关描述。
开始:
调用AddrSpace::ReadSourcePage()函数来从可执行文件中读一个页面到物理内存。注意,该函数仅在进程第一次访问虚页时调用。至于后续的访问,如果页面不在物理内存中,则搜索替换文件而不是源文件。替换文件由类似与MainMemory的内存帧组成,只不过它们存储在磁盘上。一组称为“SwapOwners”的TranslationEntry指针用来跟踪指向替换文件中页面的页表条目,一个类似的结构“CoreOwner”则用来跟踪指向内存中页面的页表条目。
若想得到更多信息,请阅读AddrSpace::ReadSourcePage()和Memmanager::PageIn()。
执行:
在执行阶段,仿真程序将在TranslationEntrys中设置适当的位,如:当出现写操作时置DIRTY=TRUE、当出现写或读操作时置USE=TRUE。如果仿真器处理了这样一个TranslationEntry中的存储器请求:LEGAL=TRUE但VALID=FALSE,它将自陷到MemManager::faultIn()中去,这就是你要实现的地方:给定缺页的TranslationEntry,用PageIn()、PageOut()以及你要实现的将适当的缓冲页面调入物理页的方法,更新TranslationEntry并将控制权返回给虚拟机。
阅读代码MemManager::PageFaultExceptionHandler(),它由ExceptionHandler()在接收到一个缺页异常时调用。关于如何实现MemManager::faultIn()的一些细节和几点提示都以注释的方式在MemManager::PageFaultExceptionHandler()中给出。注意:在此函数中,程序计数器的值不应加一。在处理完异常且控制权返回给缺页进程后,引起缺页的那条指令将重新执行。
剖析:
“faultIn”是“handler”,而其它各种方法则聚合成了重要的功能:
PageOut负责将页面写到备份存储中,它只处理脏页,因为其它的页面已在备份存储中或是与原始状态相比没有变化,所以其它的页面可以覆盖它;
PageIn负责将页面读入指定的物理页,若该页不在备份存储中,则从原始文件中装载;
MakeFreeFrame负责在没有空闲页时用适当的页面替换算法来选择一个牺牲页;
doUpdation是一个定时中断处理程序(在memmanager.cc文件中),它修改translationEntries中适当的位来更新历史信息。
三、阅读指南
1) 阅读本文档;
2) 阅读exception.cc、addrspace.h、addrspace.cc、memmanager.h和memmanager.cc;
3) 在translate.h中看看TranslationEntry的声明;
4) 阅读bitmap.h、bitmap.cc;
5) 阅读MemManager:: pageOut 和MemManager:: pageIn;
四、页面替换算法
4.1 NRU(Not Recently Used)算法
参考教材 4.4.2 节。
4.2 SC(Second Chance)算法
参考教材 4.4.4 节。
4.3 Clock算法
参考教材 4.4.5 节。
4.4 Working Set算法
参考教材 4.4.8 节。
4.5 Aging算法
参考教材 4.2.7 节。
六、编译测试
在userprog目录中键入:
make depend
make
有三个测试程序:test1、dump和test2,但只有一个(test2)充分测试了上述算法。在userprog目录中键入:
nachos –M 1 0 –x ../test/test2 测试NRU算法
nachos –M 2 0 –x ../test/test2 测试FIFO算法
nachos –M 3 0 –x ../test/test2 测试SC算法
nachos –M 4 0 –x ../test/test2 测试CLOCK算法
nachos –M 5 0 –x ../test/test2 测试WS算法
nachos –M 6 5 –x ../test/test2 测试AGE算法
源代码包中提供了各个调度算法的参考答案,文件名为test.?.std。
七、提交结果
实验分组进行,每两个人一组。实验三和实验四分组必须相同。
1) 实验报告;(电子文档,格式如bst301-305-4.doc, 包括修改后文件所在路径,修改的相关代码,结果及分析。)
2) 修改过的源代码;
注意:修改代码的格式如下:
#ifdef CHANGE
你的代码
#else
原有的代码
#endif
给mp3/userprog/Makefile中DEFINES加上CHANGE:
DEFINES = -DTHREADS -DCHANGE