操作系统课程设计内存管理.doc

上传人:文库蛋蛋多 文档编号:2392234 上传时间:2023-02-17 格式:DOC 页数:33 大小:90KB
返回 下载 相关 举报
操作系统课程设计内存管理.doc_第1页
第1页 / 共33页
操作系统课程设计内存管理.doc_第2页
第2页 / 共33页
操作系统课程设计内存管理.doc_第3页
第3页 / 共33页
操作系统课程设计内存管理.doc_第4页
第4页 / 共33页
操作系统课程设计内存管理.doc_第5页
第5页 / 共33页
点击查看更多>>
资源描述

《操作系统课程设计内存管理.doc》由会员分享,可在线阅读,更多相关《操作系统课程设计内存管理.doc(33页珍藏版)》请在三一办公上搜索。

1、作者:李晓琳 200800300117 刘泽民 200800300153三、实现系统调用与内存管理设计目标:实现fork,exec,exit与join系统调用。实现Nachos中用户程序的装入和内存页式转换机制,实现多道程序驻留内存实现带有TLB机制的的内存管理机制。设计背景:在nachos中,Thread类是来模拟一个线程的。在Thread类中,模拟了一个系统栈,并且在这个栈中保存系统寄存器的值。这里所说的系是指nachos运行的环境,对我们来说,就是所在的Linux系统。因为nachos要模拟线程的切换,因此必须要有能保存真实机器的CPU中的寄存器内容的地方。这就是说nachos自己实现了

2、一个线程库。在一个线程刚创建时,其处在JUST_CREATE状态,并且未分配系统栈。Thread类中,还有一个很重要的函数是fork,这个函数接收一个函数指针作为参数。在这个函数中,nachos会初始化这个线程的系统栈空间,并且会把所传入的函数的首址放在栈顶,这样,当这个线程被第一次运行的时候,就会从传入的这个函数处开始运行。在线程还维护了一个AddrSpace类型的指针。当调用exec时,就会从文件中装载并初始化进程的用户空间。在nachos上,可执行文件是noff格式的。这种格式的文件中,包括一个文本段与三个数据段,并且在文件头中记录了其在虚拟空间的起始位置、在文件中的起始位置,以及大小,

3、这样可以分别来初始化其用户空间的代码段、初始化数据段与未初始化数据段。这时候可以认为这个线程已经变成了一个进程。在nachos中,对机器原模拟是在machine类中。在这个类中,用两个整型数组分别来模拟寄存器与内存。在machine中,有一个Run函数,这个是用来模拟机器的运行的。这个函数是一个死循环,在每一次循环的时候,首先从用户空间中取一条指令,然后在一个大的switch语句中解释执行指令。在userpro目录下,有一个system.h的头文件,在这个头文件中,声明了与系统调用有关的函数头。对于test下的测试程序,就可以通过调用这个头文件中声明的函数来实现系统调用。在用户程序被编译完成后

4、,在函数调用的时候,首先会把参数放到r4-r7这几个寄存器中去,然后会把相应的系统调用编译成下而的指令:addiu $2,$0,SC_Haltsyscallj$31.end Halt即首先是把系统调用的类型放入r2,然后再执行系统调用指令。在nachos内部,是用RaiseException来模拟系统调用的,这个函数会调用ExceptionHandle,依靠分支来处理各种系统调用。设计分析: 制约Nachos实现多用户程序的根本原因在于Nachos在建立用户程序的时候,令虚拟地址和物理地址一一映射。每当一个新的用户程序建立的时 候,虚拟地址和物理地址都是从0开始分配,这样新的用户程序将会冲掉原

5、来在物理0开始的旧用户程序,发生错误。克服此种缺陷的方法之一是使用位示图分配物 理地址。在做虚存和物理地址的映射时,使用bitmap的find函数分配虚存对应的物理地址,但是如此使用bitmap之后,当处理虚地址到内存的映射 的时候,就又不得不改用一个一个segment地读取,那么如果采用code segment 和 data segment连续地在物理地址中存放,那么在读取code和data的时候必须首先判断是否是从一个segment 0 端开始,如果是,万事大吉,如果不是,那么以后每次都要分两次读一个segment,控制逻辑十分复杂,找data的初始位置的时候也很混乱。所以采取如 下方案:

6、保留一部分内存碎片,code和data 存放的时候都始终从一个segment的0开始,如果最后一部分不满一个segment,算为一个segment,剩余部分为碎片。实现Nachos系统调用fork,exec,exit与join实现Nachos的系统调用的时候,程序的执行采用的是异常中断的方法,接住异常的类在userprog/exception.cc,必须在此类中添加处理fork,exec,exit与join的方法。关键代码及注释:用户程序入口,用户空间:voidStartProcess(_int fn)char *filename = (char*)fn; OpenFile *executab

7、le = fileSystem-Open(filename); AddrSpace *space; if (executable = NULL) printf(Unable to open file %sn, filename); return; space = new AddrSpace(executable,filename); currentThread-space = space; delete executable;/ close file PTEntry *newEntry = new PTEntry(); newEntry-pid = interrupt-getNewSpaceI

8、d(); newEntry-name = Start; newEntry-ppid = -1; newEntry-startTime = stats-totalTicks; pTable-SortedInsert(void *)newEntry,newEntry-pid); space-Print(); space-InitRegisters();/ 设置寄存器内容 space-RestoreState();/ load page table register machine-Run();/ 运行用户程序 ASSERT(FALSE);/ machine-Run never returns;/

9、the address space exits/ by doing the syscall exitvoid Start(char *filename)Thread *t1 = new Thread(firstThread);t1-Fork(StartProcess,(_int)filename);AddrSpace:AddrSpace(OpenFile *executable,char* fn) NoffHeader noffH; unsigned int i, size; noffname = new char128; replacePos=0; strcpy(noffname,fn);

10、executable-ReadAt(char *)&noffH, sizeof(noffH), 0);/读取文件头信息。 if (noffH.noffMagic != NOFFMAGIC) &(WordToHost(noffH.noffMagic) = NOFFMAGIC) SwapHeader(&noffH); ASSERT(noffH.noffMagic = NOFFMAGIC); /计算noff文件总大小. size = noffH.code.size + noffH.initData.size + noffH.uninitData.size+ UserStackSize;/ we ne

11、ed to increase the size/ to leave room for the stack numPages = divRoundUp(size, PageSize);/所占页数 size = numPages * PageSize;/所占内存总大小,含内碎片。 /ASSERT(numPages NumClear(),numPages); int emptyNum = bitMap-NumClear(); if(emptyNum numPages) /printf(内存足够,不用虚拟内存n);/全部装入。 DEBUG(a, Initializing address space,

12、num pages %d, size %dn,numPages, size);/新建一个页表。pageTable = new TranslationEntrynumPages;/初始化页表。for (i = 0; i Find();ASSERT(pageTablei.physicalPage = 0);pageTablei.valid = TRUE;pageTablei.use = FALSE;pageTablei.dirty = FALSE;pageTablei.readOnly = FALSE; / if the code segment was entirely on a separat

13、e page, we could set its pages to be read-onlybzero(&machine-mainMemorypageTable0.physicalPage*PageSize, size);if (noffH.code.size 0) /装载代码段DEBUG(a, Initializing code segment, at 0x%x, size %dn, noffH.code.virtualAddr, noffH.code.size);executable-ReadAt(&(machine-mainMemorynoffH.code.virtualAddr+pag

14、eTable0.physicalPage*PageSize),noffH.code.size, noffH.code.inFileAddr);if (noffH.initData.size 0) /装载数据段。DEBUG(a, Initializing data segment, at 0x%x, size %dn, noffH.initData.virtualAddr, noffH.initData.size);executable-ReadAt(&(machine-mainMemorynoffH.initData.virtualAddr+pageTable0.physicalPage*Pa

15、geSize),noffH.initData.size, noffH.initData.inFileAddr); else printf(内存不足,虚拟内存n);系统调用:shell.ccintmain() SpaceId newProc,id,id2; OpenFileId input = ConsoleInput; /stdin OpenFileId output = ConsoleOutput; /stdout OpenFileId redirectFile; char ch, buffer20; char bufferCMD120,bufferCMD220,bufferCMD20,bu

16、fferArg20; int i,j; int count=0,d=0; PrintStr(*nSHELL:n1。支持用户程序并发执行,如 prt;fib 24。n2。支持重定向 如sortmyfilenamen*); while(1) PrintStr(nNachos); i = 0; do Read(&(bufferi), 1, input); while( bufferi+ != n); buffer-i = 0; if(i0)/解析命令串。if(StrCmp(buffer,halt)PrintStr( User Want to Haltn);Halt();continue;else i

17、f(StrCmp(buffer,ps)PS();continue;else if(StrCmp(buffer,ls)/LS();continue;else if(find(buffer,;)=0)/有 ;号 要并发split(buffer,;,bufferCMD1,bufferCMD2);id=Fork();if(id=0)/child1Yield();Yield();if(find(bufferCMD1, )=0)split(bufferCMD1, ,bufferCMD,bufferArg);Exec(bufferCMD,bufferArg);elseExec(bufferCMD1,0);e

18、lse/parentid2 = Fork();if(id2=0)/child2Yield();if(find(bufferCMD2, )=0)split(bufferCMD2, ,bufferCMD,bufferArg);Exec(bufferCMD,bufferArg);elseExec(bufferCMD2,0);else/parent-againJoin(id);Join(id2);else if(find(buffer,)=0)/有 号 要重定向split(buffer,bufferCMD1,bufferCMD2);/bufferCMD1 = cmd , bufferCMD2=file

19、nameredirectFile = Open(bufferCMD2);id=Fork();if(id=0)/child1Yield();SetRedirect(redirectFile);if(find(bufferCMD1, )=0)split(bufferCMD1, ,bufferCMD,bufferArg);Exec(bufferCMD,bufferArg);elseExec(bufferCMD1,0);elseJoin(id);/Close(redirectFile);else/无 ; 单独一个id=Fork();if(id=0)/child1if(find(buffer, )=0)

20、split(buffer, ,bufferCMD,bufferArg);PrintStr(bufferCMD);PrintStr(bufferArg);Exec(bufferCMD,bufferArg);elseExec(buffer,0);elseJoin(id); Exit(0);exception.ccvoidExceptionHandler(ExceptionType which)int type=0;int count=0;char *ParamStr;char *argv;SpaceId id;int memVlaue=0;int param; switch(which)case

21、SyscallException:type = machine-ReadRegister(2);switch(type)case SC_Halt:interrupt-Halt();break;case SC_Exit:interrupt-Exit(machine-ReadRegister(4);break;case SC_ExecV:ParamStr = new char128;/预先申请128个char大小的缓冲区。domachine-ReadMem(machine-ReadRegister(4)+count,1,&memVlaue);ParamStrcount = *(char*)&mem

22、Vlaue;count+;while(*(char*)&memVlaue!=0 & countExecV(ParamStr);machine-WriteRegister(2,id); /R2为返回值。machine-AdvancePC();delete ParamStr;break;case SC_Exec:ParamStr = new char128;/预先申请128个char大小的缓冲区。domachine-ReadMem(machine-ReadRegister(4)+count,1,&memVlaue);ParamStrcount = *(char*)&memVlaue;count+;

23、while(*(char*)&memVlaue!=0 & countReadMem(machine-ReadRegister(5)+count,1,&memVlaue);argvcount = *(char*)&memVlaue;count+;while(*(char*)&memVlaue!=0 & countExec(ParamStr,argv);break;case SC_Write:ParamStr = new char100;/预先申请100个char大小的缓冲区。while(count ReadRegister(5)machine-ReadMem(machine-ReadRegist

24、er(4)+count,1,&memVlaue);if(currentThread-isRedirected)WriteFile(currentThread-redirectFileId,(char*)&memVlaue, sizeof(char);elseWriteFile(machine-ReadRegister(6),(char*)&memVlaue, sizeof(char);/ 若 R6=1 指标准输出(Console)。count+;machine-AdvancePC();delete ParamStr; break;case SC_Read:/* * 从 R6 指示的文件(或键盘

25、)中读取 R5 个char ,放在 R4 指示的内存中。 */count = machine-ReadRegister(5);while(count0)ReadPartial(machine-ReadRegister(6),(char*)&memVlaue,1);/ 若 R6=0 指keyboard。machine-WriteMem(machine-ReadRegister(4)+machine-ReadRegister(5)-count,1,memVlaue);count-;machine-AdvancePC();break;case SC_Yield:currentThread-Yield

26、();machine-AdvancePC();break;case SC_Fork:id = interrupt-Fork();machine-WriteRegister(2,id); /R2为返回值。machine-AdvancePC();break;case SC_Join:param = machine-ReadRegister(4);interrupt-Join(param);machine-AdvancePC();break;case SC_PrintKernelThreadName:printf(%s,currentThread-getName();machine-AdvanceP

27、C();break;case SC_PS:interrupt-PS();machine-AdvancePC();break;case SC_LS:/not implementprintf(* 显示文件列表 *n);printf(nnametsizetsectorstindexCountn);printf(myfilet345t12t4n);printf(myfilet345t12t4n);printf(myfilet345t12t4n);/interrupt-LS();machine-AdvancePC();break;case SC_SetRedirect:currentThread-Set

28、RedirectFileId(machine-ReadRegister(4);machine-AdvancePC();break;case SC_Create:ParamStr = new char128;/预先申请128个char大小的缓冲区。domachine-ReadMem(machine-ReadRegister(4)+count,1,&memVlaue);ParamStrcount = *(char*)&memVlaue;count+;while(*(char*)&memVlaue!=0 & countOpen(ParamStr);machine-AdvancePC();break;

29、case SC_Open:interrupt-Open();break;case SC_Close:printf(Close-n);Close(machine-ReadRegister(4);break;default:printf(Unknown Syscall TYPE=%dn,type);ASSERT(FALSE);break;break;case PageFaultException:/printf(缺页中断处理n);interrupt-PageFaultHandler(machine-ReadRegister(BadVAddrReg);/printf(缺页中断处理完毕。n);brea

30、k;default:printf(Unhandler Exception Type=%dn,which);printf(n*nNoException = %d nSyscallException = %dnPageFaultException = %dnReadOnlyException = %d nBusErrorException = %dnAddressErrorException = %dnOverflowException = %dnIllegalInstrException = %dn,NoException,SyscallException,PageFaultException,

31、 ReadOnlyException,BusErrorException, AddressErrorException,OverflowException, IllegalInstrException);ASSERT(FALSE);break; interrupt.cc/子程序退出,返回调用voidInterrupt:Exit(int statusParam)currentThread-SetExitCode(statusParam);currentThread-Finish();/系统调用Exec从用户空间取文件名,生成线程。void Interrupt:Exec(char *fileNam

32、e,char *argv)/printf(+Exec(%s,%s)-n,fileName,argv);printf(要执行的用户程序 : %s_%sn,fileName,argv);char *filename = new char40;sprintf(filename,./test/%s.noff,fileName);/释放原用户空间。DeallocMem(currentThread);OpenFile *executable = fileSystem-Open(filename);if(executable = NULL) printf(打开文件失败(%s)n, filename);ret

33、urn;AddrSpace *space;space = new AddrSpace(executable,filename);currentThread-space = space;delete executable;/printf(-Exec Print()n);space-Print();space-InitRegisters();/ set the initial register valuesspace-RestoreState();/ load page table registermachine-WriteRegister(4,1);printf(*n);printf(%d,at

34、oi(argv);printf(n*n);machine-WriteRegister(5,atoi(argv);machine-Run();/跳转去执行用户进程ASSERT(FALSE);/ machine-Run never returns;/系统调用Exec从用户空间取文件名,生成线程。内存管理SpaceId Interrupt:Fork()/printf(FORKED-n);int i=0,pid;int childNumPage = currentThread-space-getNumPage();/创建一个页表。TranslationEntry *childPageTable = new TranslationEntrychildNumPage;TranslationEntry *parentPageTable = currentThread-space-getPageTable();/复制父进程页表到新页表。for(i=0;iFind();childPageTablei.valid = pa

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号