




已阅读5页,还剩28页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
作者:李晓琳 200800300117 刘泽民 200800300153三、实现系统调用与内存管理设计目标:实现fork,exec,exit与join系统调用。实现nachos中用户程序的装入和内存页式转换机制,实现多道程序驻留内存实现带有tlb机制的的内存管理机制。设计背景:在nachos中,thread类是来模拟一个线程的。在thread类中,模拟了一个系统栈,并且在这个栈中保存系统寄存器的值。这里所说的系是指nachos运行的环境,对我们来说,就是所在的linux系统。因为nachos要模拟线程的切换,因此必须要有能保存真实机器的cpu中的寄存器内容的地方。这就是说nachos自己实现了一个线程库。在一个线程刚创建时,其处在just_create状态,并且未分配系统栈。thread类中,还有一个很重要的函数是fork,这个函数接收一个函数指针作为参数。在这个函数中,nachos会初始化这个线程的系统栈空间,并且会把所传入的函数的首址放在栈顶,这样,当这个线程被第一次运行的时候,就会从传入的这个函数处开始运行。在线程还维护了一个addrspace类型的指针。当调用exec时,就会从文件中装载并初始化进程的用户空间。在nachos上,可执行文件是noff格式的。这种格式的文件中,包括一个文本段与三个数据段,并且在文件头中记录了其在虚拟空间的起始位置、在文件中的起始位置,以及大小,这样可以分别来初始化其用户空间的代码段、初始化数据段与未初始化数据段。这时候可以认为这个线程已经变成了一个进程。在nachos中,对机器原模拟是在machine类中。在这个类中,用两个整型数组分别来模拟寄存器与内存。在machine中,有一个run函数,这个是用来模拟机器的运行的。这个函数是一个死循环,在每一次循环的时候,首先从用户空间中取一条指令,然后在一个大的switch语句中解释执行指令。在userpro目录下,有一个system.h的头文件,在这个头文件中,声明了与系统调用有关的函数头。对于test下的测试程序,就可以通过调用这个头文件中声明的函数来实现系统调用。在用户程序被编译完成后,在函数调用的时候,首先会把参数放到r4-r7这几个寄存器中去,然后会把相应的系统调用编译成下而的指令:addiu $2,$0,sc_haltsyscallj$31.end halt即首先是把系统调用的类型放入r2,然后再执行系统调用指令。在nachos内部,是用raiseexception来模拟系统调用的,这个函数会调用exceptionhandle,依靠分支来处理各种系统调用。设计分析: 制约nachos实现多用户程序的根本原因在于nachos在建立用户程序的时候,令虚拟地址和物理地址一一映射。每当一个新的用户程序建立的时 候,虚拟地址和物理地址都是从0开始分配,这样新的用户程序将会冲掉原来在物理0开始的旧用户程序,发生错误。克服此种缺陷的方法之一是使用位示图分配物 理地址。在做虚存和物理地址的映射时,使用bitmap的find函数分配虚存对应的物理地址,但是如此使用bitmap之后,当处理虚地址到内存的映射 的时候,就又不得不改用一个一个segment地读取,那么如果采用code segment 和 data segment连续地在物理地址中存放,那么在读取code和data的时候必须首先判断是否是从一个segment 0 端开始,如果是,万事大吉,如果不是,那么以后每次都要分两次读一个segment,控制逻辑十分复杂,找data的初始位置的时候也很混乱。所以采取如 下方案:保留一部分内存碎片,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 *executable = 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-getnewspaceid(); 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;/ 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); 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 need 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, 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 separate 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+pagetable0.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*pagesize),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,bufferarg20; 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 if(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);else/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=filenameredirectfile = 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)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 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*)&memvlaue;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+;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-readregister(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 指示的文件(或键盘)中读取 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();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-advancepc();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-setredirectfileid(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;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);break;default:printf(unhandler exception type=%dn,which);printf(n*nnoexception = %d nsyscallexception = %dnpagefaultexception = %dnreadonlyexception = %d nbuserrorexception = %dnaddresserrorexception = %dnoverflowexception = %dnillegalinstrexception = %dn,noexception,syscallexception,pagefaultexception, readonlyexception,buserrorexception, addresserrorexception,overflowexception, illegalinstrexception);assert(false);break; interrupt.cc/子程序退出,返回调用voidinterrupt:exit(int statusparam)currentthread-setexitcode(statusparam);currentthread-finish();/系统调用exec从用户空间取文件名,生成线程。void interrupt:exec(char *filename,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);return;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,atoi(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 = parentpagetablei.valid;childpagetablei.use = parentpagetablei.use;childpagetablei.dirty = parentpagetablei.dirty;childpagetablei.readonly = parentpagetablei.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 *forkedthread = 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-starttime = 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 pid;/系统调用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();/将父进程挂起执行子进程/子进程执行结束,唤醒父进程pcrentry = (pcrtentry*)pcrtable-searchan
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《拿来主义》课件 统编版高中语文必修上册
- 北京素描三级考试题目及答案
- WJM664-生命科学试剂-MCE
- DL-Cytarabine-13C3-生命科学试剂-MCE
- 北京安全员证考试试题及答案
- 2-3-Oxidosqualene-d6-Squalene-oxide-d-sub-6-sub-生命科学试剂-MCE
- 美容的考试题及答案
- 电焊培训知识大全课件
- 高校消防知识培训课件新闻稿
- 保安职业体能考试题库及答案
- FABE销售法则销售培训课件
- 电力电子技术第五版(王兆安)课件全
- 人工智能导论课件
- 有效沟通:金字塔原则课件
- 苏科版三年级上册劳动第二课《学定时》课件(定稿)
- 中国古代的美育思想课件
- 心理学专业英语基础51057048
- 日周月安全检查记录表
- 重庆物业服务收费管理办法-重庆物价局
- 2021年中国华电集团公司组织架构和部门职能
- GA∕T 1046-2013 居民身份证指纹采集基本规程
评论
0/150
提交评论