Lab3 只是草草的做了一下,今天上课发现确实有很多问题。还是得用虚存来实现,不过实在是懒得弄了。。
1 修改exception.cc中的方法,当发生TLB MISS时,如果该页不在内存中,从磁盘中加载该页。
else if(which == PageFaultException)
{ //如果发生了缺页中断
DEBUG('p',"page fault\n");
//获得虚拟地址
int addr = machine->ReadRegister(BadVAddrReg);
//如果该页不在内存中,将硬盘中的数据拷贝到内存
if(!machine->LRUSwap(addr))
{
machine->swapPage(addr);
//再将页表项拷贝到tlb表中
machine->LRUSwap(addr);
}
stats->numPageFaults++;
//DEBUG('p',"swapNum is %d\n",machine->swapNum);
}
2. 在machine中添加属性,以用于缺页处理,从文件中读取某一页的内容到内存。
NoffHeader noffH; // 用来从磁盘中读取数据到内存
OpenFile *executable; // 打开文件
在addrspace.cc中修改构造方法,为machine初始化属性
//用来处理缺页置换
machine->noffH = noffH;
machine->executable = executable;
在此时方法时注释掉该句,由于文件在缺页置换时还会用到,不能及时删除
//delete executable; // close file
3.当该页不在内存时,调用 swapPage方法,从磁盘中读取一页到内存的方法。
bool
Machine::swapPage(int addr)
{
int vpn = addr/PageSize;
int offset = addr%PageSize;
int swapVpn = -1;
int ppn = machine->mBitmap->Find();
int min = pageTable[0].lastUseTime;
if(ppn==-1) //内存中没有空闲空间,利用LRU找到被置换的页
{
ppn = 0;
for(int i = 0;i < pageTableSize; i++)
{
if(pageTable[i].lastUseTime < min && pageTable[i].valid == TRUE)
{
min = pageTable[i].lastUseTime;
ppn = pageTable[i].physicalPage;
swapVpn = i;
}
}
}
//DEBUG('p',"ppn:%d\n",ppn);
if(ppn == -1)
return FALSE;
//从硬盘中加载该页的数据
NoffHeader noffH = machine->noffH;
//int vAddr = vpn*PageSize; //该页的虚拟起始地址
//DEBUG('p',"addr:%d,pAddr:%d,vAddr:%d\n",addr,pAddr,vAddr);
//DEBUG('p',"code.virtualAddr:%d,code.size:%d,code.inFileAddr:%d\n",
// noffH.code.virtualAddr,noffH.code.size,noffH.code.inFileAddr);
//DEBUG('p',"initData.virtualAddr:%d,initData.size:%d,initData.inFileAddr:%d\n",
// noffH.initData.virtualAddr,noffH.initData.size,noffH.initData.inFileAddr);
//DEBUG('p',"openFile:%d\n",executable->GetFileId());
//判断置换页中的每一个字节是在代码段还是在数据段
for(int i = 0;i < PageSize;i++)
{
int vAddr = vpn*PageSize + i; //要拷贝的字节的虚拟地址
int pAddr = ppn*PageSize + i; //要拷贝的字节的物理地址
//如果在代码段
if(vAddr>=noffH.code.virtualAddr
&&vAddr<(noffH.code.virtualAddr+noffH.code.size))
{
machine->executable->ReadAt(&(machine->mainMemory[pAddr]),
1,noffH.code.inFileAddr+vAddr);
}//如果在数据段
else if(addr>=noffH.initData.virtualAddr
&&addr<(noffH.initData.virtualAddr+noffH.initData.size))
{
machine->executable->ReadAt(&(machine->mainMemory[pAddr]),
1,noffH.initData.inFileAddr+vAddr-noffH.initData.virtualAddr);
}
}
//更新pagevTable表
pageTable[vpn].virtualPage = vpn;
pageTable[vpn].physicalPage = ppn;
pageTable[vpn].valid = TRUE;
pageTable[vpn].lastUseTime = stats->totalTicks;
//更新被置换掉的页表项
if(swapVpn != -1)
{
pageTable[swapVpn].physicalPage = 0;
pageTable[swapVpn].valid = FALSE;
//如果被置换掉的页已经被修改
//写回到磁盘
if(pageTable[swapVpn].dirty == TRUE)
{
DEBUG('p',"swap the page to disk.\n");
}
}
return TRUE;
}