Nachos地址空间扩展

一、实验目的:

1.实现nachos中用户程序的装入和内存页式转换机制,

2.实现带有TLB机制的内存管理机制

3.实现几种基本的系统调用功能

4.实现虚拟内存管理机制

5.通过多用户程序并发执行验证以上你的设计是否成功的实现了。

6.扩展现有的class AddrSpace的实现,使得Nachos可以实现多用户程序,完成系统调Exec

使Nachos按页分配内存空间

二、实验环境:

   硬件环境(虚拟机下):1G内存 60G硬盘空间 CPU主频:2.1GHz

    软件环境:linux操作系统(gdbg++ gccmips交叉编译器配置)

三、实验内容:

1.  首先编写实验6Print函数,为了可以显示内存空间的分配。以下为Print函数的实现:

addrSpace.cc:

void AddrSpace::Print()

{

   printf("page table dump: %d pages in total\n", numPages);

   printf("============================================\n");

   printf("\tVirtPage, \tPhysPage\n");

   for(int i=0; i < numPages; i++) {

      printf("\t%d, \t\t%d\n", pageTable[i].virtualPage, pageTable[i].physicalPage);

   }

   printf("============================================\n\n");

}

#include "syscall.h"

int

main()

{

   int i,j,k;

   k=3;

   i=2;

   j=i-1;

   k=i-j+k;

    Halt();

    /* not reached */

}

#include "syscall.h"

static int a[40];

int

main()

{

   int i,j,k;

   k=3;

   i=2;

   j=i-1;

   k=i-j+k;

    Halt();

    /* not reached */

}

2.  编写一个exec.c的源码,然后编译生成一个可执行文件,exec.noff

#include "syscall.h"

int main()

{

SpaceId pid;

pid=Exec("../test/halt.noff");

Halt();

}

3.  Nachos原来实现AddressSpace分配的时候没有使用bitmap来寻找空闲页,而是直接的从0号内存空间开始分配,因而需要修改成使用bitmapfind函数分配内存空间

pageTable = new TranslationEntry[numPages];

    for (i = 0; i < numPages; i++) {

   pageTable[i].virtualPage = i;  // for now, virtual page # = phys page #

//=======================================================

   pageTable[i].physicalPage = freePageMap->Find();

//=======================================================

   pageTable[i].valid = TRUE;

   pageTable[i].use = FALSE;

   pageTable[i].dirty = FALSE;

   pageTable[i].readOnly = FALSE;

}

   其中,要声明一个位试图的是对象,在AddrSpace

//================================

static BitMap *freePageMap = NULL;

//================================

AddrSpace::AddrSpace(OpenFile *executable)

{

    NoffHeader noffH;

    unsigned int i, size;

//================================================

    if(freePageMap == NULL) {

   freePageMap = new BitMap(NumPhysPages);

    }   

//================================================

    executable->ReadAt((char *)&noffH, sizeof(noffH), 0);

    if ((noffH.noffMagic != NOFFMAGIC) &&

      (WordToHost(noffH.noffMagic) == NOFFMAGIC))

      SwapHeader(&noffH);

    ASSERT(noffH.noffMagic == NOFFMAGIC);

// how big is address space?

    size = noffH.code.size + noffH.initData.size + noffH.uninitData.size

        + UserStackSize; // we need to increase the size

                 // to leave room for the stack

    numPages = divRoundUp(size, PageSize);

    size = numPages * PageSize;

    ASSERT(numPages <= NumPhysPages);     // check we're not trying

                 // to run anything too big --

                 // at least until we have

                 // virtual memory

    DEBUG('a', "Initializing address space, num pages %d, size %d\n",

              numPages, size);

4.  计算加载一个程序需要的页表的数目

numPages = divRoundUp(size, PageSize);

size = numPages * PageSize;

5.  实现Nachos的系统调用,采用的是触发异常中断的,在userprog/exception.cc,添加SC_Exec异常,存放要执行的文件的路径的字符串的首地址存放在4号寄存器中,因此可以通过这个方式找到文件的路径,从而使用文件系统提供的方法打开这个文件:

 void

ExceptionHandler(ExceptionType which)

{

    int type = machine->ReadRegister(2);

    //printf("exception handler\n");

    if ((which == SyscallException) && (type == SC_Halt)) {

DEBUG('a', "Shutdown, initiated by user program.\n");

printf("HALT!!\n");

//printf("AddrSpace addr is %d\n", (int)currentThread->space);

   interrupt->Halt();

    } else if((which == SyscallException) && (type == SC_Exec)) {

printf("exception exec\n");

        int fileAddr = (machine->ReadRegister(4));

char* filename = readFileName(fileAddr);

//printf("filename is :%s\n", filename);

OpenFile *executable = fileSystem->Open(filename);

//printf("file opened!\n");

if(executable == NULL) {

             printf("Unable to open file \n", filename);

     return;

}

//printf("Old AddrSpace addr is %d\n", (int)currentThread->space);

AddrSpace *space = new AddrSpace(executable);

delete executable;

delete filename; 

//machine->Debugger();

space->InitRegisters();

space->RestoreState();

delete currentThread->space;

currentThread->space = space;  

machine->WriteRegister(2, (int)space);

//printf("register 2 written back. The value is :%d\n", (int)space);

//pcInc();

   return;

    } else if((which == SyscallException) && (type == SC_Exit)) {

//printf("EXIT!!\n");

int status = machine->ReadRegister(4);

printf("STATUS IS %d\n", status);

//printf("AddrSpace addr is %d\n", (int)currentThread->space);

if(status == 0) {

    //currentThread->Finish();

    machine->WriteRegister(2, 0);

}

pcInc();   

return;   

    } else {

printf("Unexpected user mode exception %d %d\n", which, type);

ASSERT(FALSE);

    }

}

6.  结果分析:编译成功之后,输入命令 ./nachos x ../test/Exec.noff

运行结果:

四 实验体会及总结

结论分析与体会:

Nachos之前没有实现按页分配地址空间,物理页和逻辑页地址一致,而且数据段代码段连续分配,每当一个新的用户程序建立的时候,虚拟地址和物理地址都是从0开始分配,这样新的用户程序将会冲掉原来在物理0开始的程序。

因而使用位示图分配物理地址。使用bitmapfind函数分配虚存对应的物理地址,在为数据段和代码段写入数据的时候是以扇区为单位的,而不是原有的连续一个文件的读入连续的内存。Nachos操作系统通过中断的方式实现系统调用。需要增加userprog/exception.cc中的内容,即必须在此类中添加处理Exec的方法

你可能感兴趣的:(NachOs,地址空间扩展)