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

上传人:仙*** 文档编号:31471901 上传时间:2021-10-12 格式:DOC 页数:33 大小:112KB
收藏 版权申诉 举报 下载
操作系统课程设计内存管理_第1页
第1页 / 共33页
操作系统课程设计内存管理_第2页
第2页 / 共33页
操作系统课程设计内存管理_第3页
第3页 / 共33页
资源描述:

《操作系统课程设计内存管理》由会员分享,可在线阅读,更多相关《操作系统课程设计内存管理(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 = n

35、ew TranslationEntrychildNumPage;TranslationEntry *parentPageTable = currentThread-space-getPageTable();/复制父进程页表到新页表。for(i=0;iFind();childPageTablei.valid = parentPageTablei.valid;childPageTablei.use = parentPageTablei.use;childPageTablei.dirty = parentPageTablei.dirty;childPageTablei.readOnly = pare

36、ntPageTablei.readOnly;if(2*childNumPage NumPhysPages)printf(内存过少于正常执行Fork所需内存。n);Halt();/复制内存。for(i=0;imainMemoryi+childPageTable0.physicalPage*PageSize = machine-mainMemoryi+parentPageTable0.physicalPage*PageSize;AddrSpace *forkedSpace = new AddrSpace(childPageTable,childNumPage);Thread *forkedThre

37、ad = new Thread(Forked_Thread);forkedThread-space = forkedSpace;forkedThread-SaveUserState();pid = getNewSpaceId();forkedThread-SetPid(pid);forkedThread-Fork(Forked,0);PTEntry *newEntry = new PTEntry();newEntry-pid = pid;newEntry-name = Forked;newEntry-ppid = currentThread-GetPid();newEntry-startTim

38、e = stats-totalTicks;pTable-SortedInsert(void *)newEntry,newEntry-pid);PCRTEntry *pcrEntry = new PCRTEntry();pcrEntry-pid = pid;pcrEntry-ppid = currentThread-GetPid();pcrEntry-isJoined = false;pcrEntry-join_sem = 0;pcrEntry-exitCode = 9999;pcrTable-SortedInsert(void *)pcrEntry,pcrEntry-pid);return p

39、id;/系统调用Join等待id线程完成。void Interrupt:Join(SpaceId id)PCRTEntry *pcrEntry = (PCRTEntry*)pcrTable-Search(id);if(pcrEntry=NULL)return;PTEntry *pEntry = (PTEntry*)pTable-Search(id);if(pEntry=NULL)return;pcrEntry-isJoined = true;pcrEntry-join_sem = new Semaphore(join_sem,0);pcrEntry-join_sem-P();/将父进程挂起执行

40、子进程/子进程执行结束,唤醒父进程pcrEntry = (PCRTEntry*)pcrTable-SearchAndRemove(id);int childExitCode = pcrEntry-exitCode;delete pcrEntry;以上设计实验输出结果的分析:$ cd /media/学习/大三上学期/操作系统课程设计/实验代码/实验三代码/nachos-3.4/code/userprog/$ ./nachos -x ./test/shell.noff结果如下:OpenForReadWrite ./test/shell.noff-共 35 个页=Vitual Phys0, 01,

41、12, 23, 34, 45, 56, 67, 78, 89, 910, 1011, 1112, 1213, 1314, 1415, 1516, 1617, 1718, 1819, 1920, 2021, 2122, 2223, 2324, 2425, 2526, 2627, 2728, 2829, 2930, 3031, 3132, 3233, 3334, 34=*SHELL:1。支持用户程序并发执行,如 prt;fib 24。2。支持重定向 如sortmyfilename*Nachos 在nachos中输入prt2;fib 20结果如下:Nachosprt2;fib 20要执行的用户程序

42、: prt2_0OpenForReadWrite ./test/prt2.noff-共 21 个页=Vitual Phys0, 351, 362, 373, 384, 395, 406, 417, 428, 439, 4410, 4511, 4612, 4713, 4814, 4915, 5016, 5117, 5218, 5319, 5420, 55=*0*prt_2 is Running0要执行的用户程序 : fib_20OpenForReadWrite ./test/fib.noff-共 19 个页=Vitual Phys0, 561, 572, 583, 594, 605, 616,

43、627, 638, 649, 6510, 6611, 6712, 6813, 6914, 7015, 7116, 7217, 7318, 74=*20*prt_2 is Running1第20项Fibnacci数是:6765prt_2 is Running2prt_2 is Running3prt_2 is Running4prt_2 is Running5prt_2 is Running6prt_2 is Running7prt_2 is Running8prt_2 is Running9Nachos分析:有结果分析可知,输入$ ./nachos -x ./test/shell.noff后,系统调用Fork()函数创建父进程即nachos的shell。成功运行nachos后输入prt2;fib 20,在父进程下创建两个子进程,分别为其分配用户程序空间,并发执行程序,此时在shell中风别调用了Join(id);Join(id2);函数,待两子进程运行结束后,会返回父进程,即shell,以等待下个用户程序的执行。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!