还剩22页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
操作系统课程设计报告班级团队成员:为只读这个方法失败不会抛出异常,它总会返回传送的位数,即使是零修改Userprocess.loadSections,根据所需为进程分配页数用你决定的分配规则这个方法还要为进程开启页表structure,这样进程就被加载到当前物理内存页中122题目分析与实现方案Nachos为不同进程应分配完全不同的物理内存,但不支持动态内存分配,所以需要分配的内存在装入程序时就可以确定了(代码,数据,堆栈部分)故在装入程序时就为每个进程一次性分配固定的物理内存,在进程结束时收回它们这里还需要实现如下简单的虚拟内存方案每个进程的地址空间是连续的虚拟内存,但这些连续的虚拟页面在物理内存中却不一定是连续的这个方案的简单之处在于,虚拟空间的总容量和物理空间的总容量相等,映射机制只是从虚拟内存到物理内存的一一映射除了内存的分配,内存的读写也要体现出映射机制方案页表pageTable以虚拟页号为下标,其中的每个项目是一个machine.TranslationEntry类型的对象,存放了一个页的下列信息物理页号,虚拟页号,是否有效,是否只读,是否被用过,是否脏在UserKernel中定义一个全局队列memoryLinkedList用于存放当前空闲的物理页号,一个保护内存互斥访问的锁allocateMemoryLocko开始时,memoryLinkedList包括所有的物理页面当启动新进程时,UserProcess.load负责从磁盘装入进程过程UserProcess.loadSections完成如下操作先获得allocateMemoryLock,锁定内存该进程需要的页面数己知,保存在numPage变量中与memoryLinkedList比较,判断空余存储空间是否足够分配物理页(UserKerneL allocatePages)时从memoryLinkedList中出队相应数量的页面(返回的是物理页号的数组)2)整个需要装入的进程是一个machine.CoffSection类型的对象,包括若干个页在loadSection中,在释放allocateMemoryLock前应该创建一个页表3)得到可用的物理页号后,就装入所有的页,为段中每个虚拟页在pageTable中创建一个新的TranslationEntry对象并为其赋上相应的虚拟页号和物理页号等信息,然后将原来section对象的读写权限等转移,然后并调用CoffSection.loadPage将页的内容读入读入时进行物理地址和逻辑地址的关联,然后把程序的每一块按照顺序对应于物理地址导入到内存中完成了题目的“保持物理页的全局链接表”的要求4)在进程结束时,对于页表中所有的页面,只要将其虚拟页号放入memoryLinkedList队歹UserProcess.readVirtualMemory读虚拟内存读内存时,要先利用页表将逻辑地址转换为物理地址然后再将内存数据复制到数组中类似地,UserProcess.writeVirtualMemory写虚拟内存,其方法与readVirtualMemory类似,要先利用页表将逻辑地址转换为物理地址然后再将数组数据复制到内存中,并注意取页面时要检查页面是否为只读
1.
2.3关键点与难点在loadSection中,在导入coff之前应该创建一个页表,进行物理地址和逻辑地址的关联,然后把程序的每一块按照顺序对应于物理地址导入到内存中这样就完成了题目的“保持物理页的全局链接表”的要求读写内存时,要先利用页表将逻辑地址转换为物理地址然后再将内存数据复制到数组中,取页面时要检查页面是否为只读读写内存时要注意判断内存是否已满,数组是否已满,是否有错误参数比如写入数据的长度0,另外题目要求无论读写是否成功都不报错,而是返回读写数据的长度
1.
2.4实现代码UserKernel//保护内存互斥访问的锁public staticLock allocateMemoryLock//全局队列,用于存放当前空闲的物理页号public staticLinkedListInteger memoryLinkedListUserProcessprotected booleanloadSectionsO{//获取分配内存的锁,锁定内存UserKernel allocateMemoryLockacquireO;//判断能否装载if numPagesUserKernel.memoryLinkedList sizeO{coff.close0;Lib debug/z dbgProcess.¥tinsufficient physicalmemory;UserKernel allocateMemoryLockrelease;//返回装载失败return false1//创建页表pageTable=new TransI ationEntrynumPages;for inti=0:inumPages:i++{int nextPage=UserKernel memoryLinkedListremove9;pageTableI i]=new TranslationEntryi,nextPage,true,false.false,false;//释放锁UserKernel allocateMemoryLockre Iease0;for ints=0;scoff.getNumSectionsO;s++{CoffSection sectioncoff getSections;//获得sect ionLib debugz/dbgProcess¥tinitializing+section getNameD+“section+section.getLength+“pages”;for inti=0isection.getLength;i++{int vpn=section.getFirstVPNO+i;//标记只为已读pageTable[vpn]readonly=section.isReadOnlyO;section.loadPagei,pageTable vpnppn;return true;public intreadV irtuaI Memoryint vaddr,byte[]data,int offset,int Iength//保证偏移量与长度都为正,偏移量+长度仁总的数据长度Lib asserset=0length=0offset+length=data.length;byte口memory=Machine processor^.getMemory0//获得需求if lengthpageSize*numPages-vaddr//判断能否读取length=pageSize*numPages-vaddrif data,length-offsetlength length=data,length-offset;int transferredbyte=0do1int pageNumProcessor pageFromAddressvaddrtransferredbyteif pageNum0||pageNum=pageTable.length return0:int pageOffsetProcessor offsetFromAddress^^x+transferredbyte;int leftByte=pageSize-pageOffset;int amount二Math/leftByte,length-transferredbyte;int real Address=pageTable[pageNum]ppn*pageSize+pageOffset;System arraycop/memory,realAddress,data,offset+transferredbyte,amount;transferredbyte=transferredbyte+amount;]while transferredbytelength;return transferredbyte1public intwriteVirtuaIint vaddr,byte[]data,int offset,int lengthLib assertTrueB弋弋set=0length=0offset+length=data.length;byte」memory二Machine processor^.getMemory:if lengthpageSize*numPages-vaddr length=pageSize*numPages-vaddr;if data,length-offsetlength length=data,length-offset;int transferredbyte=0doint pageNum=Processor pageFromAddressvaddr+transferredbyte ifpageNum0||pageNum=pageTable.length return0;int pageOffsetProcessor offsetFromAddressvaddr+transferredbyte;int leftByte=pageSize-pageOffset;int amount=Math min{IeftByte,length-transferredbyte;int realAddress=pageTable[pageNum.ppn*pageSize+pageOffsetSystem arraycopyA^z offset+transferredbyte.memory.realAddress,amount;transferredbyte=transferredbyte+amountI whiletransferredbytelength;return transferredbyte
11.3Task
2.3实现系统调用
1.
3.1题目要求实现系统调用exec,join,and exit,同样在syscall.h此外,所有通过寄存器来Exec和加入的地址是虚拟地址你应该使用readVirtualMemory和readVirtualMemoryString在内核和用户进程之间传递内存同样,你必须防止这些系统调用注意,子过程的状态是进程完全私有的这意味着,父进程和子进程不直接共享存储器或文件描述符注意两个过程当然可以打开相同的文件;例如,所有的进程应该有的0和I映射到系统控制台的文件描述符不像KThread.joinO,只有一个进程的父进程可以调用join举例来说,如果A创建B并且B创建C,A不允许join到C中,但B被允许join到C加入需要一个进程ID作为参数,用于唯一标识其父母希望加入的子进程进程ID应该是全局唯一的正整数,在每个进程创建时分配虽然在这个项目的唯一使用的进程ID是在join,进程ID是整个系统中的所有正在运行的进程是唯一的以后项目阶段很重要解决这个问题的最简单的方法就是保持一个表明接下来的进程ID分配的静止计数器由于该进程ID是int类型,则有可能对是否存在在系统中的许多过程这个值溢出对于这个项目,你不必要处理这种情况下,也就是说,假定该方法ID计数器不会溢出当进程调用exit,它的线程应立即终止,而这个过程应该清理与它相关的任何状态也就是释放内存,关闭打开的文件等如果一个进程异常退出执行相同的清理在退出过程的退出状态应转移到父进程,如果父调用join系统调用一个进程退出状态的异常与否取决于你对于join的目的,如果它任何状态下调用退出函数,那么一个子进程正常退出,如果内核杀死它例如,由于未处理的异常则是不正常的最后一个过程调用exit应使machine类暂停,通过Kernel.kernelterminate请注意,只有根进程中应允许调用halt系统调用,但最后退出的过程中应该直接调用Kernel.kernel.terminateC
1.
3.2题目分析与实现方案在该系统调用中,第一个参数为文件名地址,第二个参数为参数个数,第三个参数为参数表指针.需要做的工作是读虚拟内存获得文件名
2.处理参数首先用第三个参数作为虚拟内存地址得到参数表数组的首址,然后用readVirtualMemoryString依次读出每个参数
3.用UserProcess.newllserProcess创建子进程,将文件和参数表加载到子进程4,用UserProcess.execute方法执行子进程,同时将这个子进程的父进程置为这个进程,再将子进程加入子进程列表join:该系统调用中,第一个参数为子进程编号,第二个参数一个地址,用于保存子进程的返回值.需要做的工作是
1.利用进程号确定join的是哪一个进程,检查childProcesses,遍历子进程链表,确定join的进程是子进程如果子进程编号不在其中则出错返回
2.获得join锁,让该进程休眠,直到子进程唤醒
3.子进程唤醒之后,将子进程的状态存入自己的内存中,判断当前进程是否正常结束结束则返回exit首先关闭coff,然后将所有的打开文件关闭,把退出的状态置入,如果该进程有父进程,看是否执行了join方法,如果执行就将其唤醒,同时将本进程从子进程链表中删除,释放内存,结束底层线程,如果是最后一个结束的进程则将系统关闭该系统调用的唯一参数为返回值需要做的工作为
1.关闭coff,关闭所有打开的文件,把退出的状态置入
2.如果该进程有父进程,看是否执行了join方法,如果执行就将其唤醒,同时将此进程从子进程链表中删除
3.调用unloadsections释放内存,调用KThread.finish方法结束当前线程
4.如果是最后一个进程,调用Machine.halt停机,修改运行的进程总数
1.
3.3关键点与难点exec实现创建子进程并执行功能,涉及执行程序地址,参数数量,参数地址相关参数,并返回子进程id join阻塞等待某子进程执行完毕;涉及参数子进程id,子进程地址,并返回-加/I exit关闭进程,清除相关信息,涉及进程状态参数,返回
0.应注意1父进程和子进程不共享任何的内存,文件或其它状态2只有父进程能对子进程进行join操作例如A执行B,B执行C,则A不允许join C,而B允许join C3需要为每个进程分配一个唯一的进程编号4exit操作将使当前进程立即结束,如果父进程对其进行join操作,返回代码这时应返I可5最后一个调用exit的进程将使系统停机
1.
1.1Task
41.2Task
51.
51.
61.
71.3Task
71.
71.
91.4Task
101.
101.
101.
111.
01.4Task
2.4实现彩票调度
1.
4.1题目要求实现彩票调度把它放在线程/Lottery Scheduler,java o注意,这个类扩展自PriorityScheduler,你应该能够重复使用的大部分该类的功能;彩票调度应是大量的额外的代码唯一的主要区别是程序从队列机制挑选一个线程彩票是持有,而不是仅仅选取优先级最高的线程你的彩票调度应实施优先级优先捐赠请注意,因为这是一个彩票调度,优先级反转实际上并不能导致饥饿!但是,你必须做优先权捐赠在彩票调度中,除了优先权的捐助,等待线程转移门票给他们等待的线程不同于标准的优先级调度,一个等待线程总是将其门票给队列所有者;即,拥有者的门票数是它自己的门票的总和与所有服务员的票,而不是最大值一定要正确地实现这一点你的解决方案应该工作,即使有几十亿的门票系统即不保持包含每票项的数组当LotteryScheduler.increasePriority被调用时,由一个进程拥有的彩票数目递增同样地,对于decreasePriority,该数量应该减一车票中系统中的车票总数目是保证不超过lnteger.MAX_VALUE的现在设置的最高优先级也是lnteger.MAX_VALUE,而不是7(PriorityScheduler.priorityMaximum)如果你愿意,你也可以假设最小的优先级提高到1(从0)142题目分析与实现方案具体过程大体为L统计总的彩票数2,生成合理中奖彩票找出持有者调度引入一个Threadstate类用来把进程和彩票数量联系在一起,但是在得到有效优先级时,是把等待自己的队列中的进程的优先级和自己的优先级加起来,总的彩票数才是自己的优先级在getEffectivePriorityNachos中将选取最大优先级的过程改成将所有等待线程的优先级(彩票数)力口至U lockHolder上(即等待者把自己拥有的彩票给获得锁的线程),其次将nextThread修改如下首先遍历一遍队列,计算出当前队列中的所有队列的彩票总数(考虑过donation后的)num Effective,其次生成一个0到num Effective-1之间的随机数random Lottery表示抽取的彩票,最后再次遍历一遍队列,用累加器t计算彩票总数,当t对应的当前值大于randomLottery时说明当前循环到的线程正好落在目标区间内,即选出该线程由于不能保存彩票的指针,所以只能遍历队列,累加线程的有效优先级,当有效优先级的总和大于等于中奖号码表示这个线程中奖,这是利用概率中的随机原则,将中奖转换为了累加找到线程后将线程从队列中取出,将其返回
1.
4.3关键点与难点彩票调度与优先级调度非常类似,只是将“优先级”的概念变成了“彩票”,即表示该线程下次被运行的几率而且在调度过程中,并不是选择彩票数最多的线程运行,而是随机抽取一彩票,让彩票的主人运行这样,彩票越多,下次得到的运行机会就越大类Lotteryscheduler继承自类Priorityscheduler,可以直接利用类Priorityscheduler的特性把进程和彩票数量联系在一起,并且彩票的“抽奖”过程只能遍历线程队列
1.
4.4实现代码public intgetEffectivePriority1//i mpIementme ifeffectivepriority\=expiredEffectivePriority return effectivePriority;effectivePriority=priority;//等待队列为空if waiters==null returneffectivePriority;//将所有等待线程的优先级彩票数加到lockHo Ider±for Iterator i=waiters.waitQueue.iteratorO;i hasNextO;{Threadstate ts=Threadstate getThreadStateKThread i.next;effectivePriority+=ts.priority;returneffectivePriority;protected ThreadstatepickNextThreadO//i mpIementme intnumEffeetive=0if waitQueueisEmpty returnnull;//计算彩票总数for Iterator i=waitQueue,iterator;i.hasNext0;Threadstate ts=Threadstate getThreadStateKThreadi.next0;numEffect ive+=ts.getEffeet ivePr iority;Random random=new Random;//随机出一个0到numEffeetive7之间的随机数表示抽取的彩票int randomLottery=random nextI ntnumEffeetive;int t=0;Threadstate toPick=null;for Iteratori=waitQueue.iteratorO;i.hasNext;Threadstate n=JhreadState getThreadStateKThread;i.next0;t+=n.getEffeet ivePr iority;if trandomLottery//当t的当前值大于randomLottery时说明当前循环到的线程正好落在目标区间内,即选出该线程toPick=nreturn toPick测试结果怪Package Explorer0—test留典1This is a testPile.,0NachosProj2t aJRE SystemLibrary[JavaSE-
1.7]-6test Bl-test[.c]assert.c岛assert.o k.Expl”“汉白弟D oD昌_tot「_t”“S3;_Prebles向J
3.docD.elzNion5m Nacho$Prqj2A1This isa test file.terminatedMachine1[Javai c»“JRE Systemlibrary[JavaSE-
1.7]Application Testing the userkernel・O testThread」is working.宿,test B.testl Thread_2is working..assertc宿Thread_3is working.asserto.atoi.c gatoi.o Thread」is working.出catc Thread_5is working.僮catcoff Thread_6is working.品cat・o由cp-c场cp.coff Thread_7is working.nachos%cp■CpbO I_test_test1|cp-test_test1C10Explorer笈日第-Problcrts京Javadoc叵D*cl=Atig RC Nacho$Proj2人_t«2t[.]_“Xt2次I This isa testfile.terminated^Machine1[Java Application]I4JRE SystemLibrary JavaSE-
1.7]latest TestingI the userkernel Thread」is working.Je$t2Thread_2is working.国assert.c喻Thread_3is working.assert.o@atoi.c Thread」is working.血atoi.o Thread_5is working.国catc Thread.6is working.昌catcoff Thread_7is working..cato qcp.c nachos%mv.testl,test28@cp.coff卜v_test1_test2品Cp.O应Frobl«ns@JATA^OC及DoclftTAti Zxplortr汉白^°O1ThisisatestFile.NachosProj2A terminatedMachine1Java Applic0src TestingtheuserkernelThread」*JRE SystemLibr is working.Thread_2is working.窗Jest访a$sert.c Thread_3is working.Threadjis届asserto working.Thread_5is working.甚atoi.c Thread_6is working.Thread_7is品atoi.o working,nachos%rm_test2国cat.c卜m_test2矣cat.coff扇cat.o[11Q cp・c.cp.coff应cp.o,echo.c configinterrupt timerprocessor consoleuser-check gradernachos
5.0j initializing.Testingtheuserkernel Random:9Thread_4is working.Random:A Thread-5is working.Random:8Thread_6is working.Random:5Thread_3is working.Random:1Thread」is working.Thread_7is working.Thread-2isworking.
一、实验要求多道程序设计I.1Task
2.1实现文件系统调用II.1题目要求实现文件系统调用(创建,打开,读,写,关闭,unlink),在syscall.h中有详细的记录,可以看一下UserProcess.java中的代码,最好把你自己写的系统调用的代码也放在这里记住你不是在实现一个文件系统,而是在给用户进程获取我们给你定义好的文件系统的能力我们在start.s里为你提供了用户进程进行系统调用所必需的汇编代码(SYSCALL会为每个系统调用产生汇编代码)其中Unlink为删除目录相并减少一个连接数,如果链接数为0并且没有任何进程打开该文件,该文件内容才能被真正删除,但是若又进程打开了该文件,则文件暂时不删除直到所有打开该文件的进程都结束时文件才能被删除
1.
1.2题目分析与实现方案系统共提供了七个系统调用halt(停机,已经提供),creat(创建并打开磁盘文件),open(打开磁盘文件),read(读可以是磁盘或屏幕),write(写10),close(关闭10),unlink(删除磁盘文件)要确保如下几点1)稳定性,不能因为一个进程的非法系统调用就使操作系统崩溃,而应该返回错误代码2)halt()调用只能由第一个进程(root process)执行3)系统调用需要读写内存时,通过readVirtualMemory和writeVirtualMemory进行4)文件名以null结尾,不超过256字符5)如果系统调用出错,应返回-16)为每个打开的10文件分配一个“文件描述符”,用整数表示,每个进程最多可以拥有16个其中和1应分配给标准输入和标准输出(即屏幕),这由SynchConsole类管理不同进程可以用相同的文件描述符处理不同的文件7)Nachos己经提供了一个简单的文件系统FileSystemCMachine包中),通过ThreadedKernel.fileSystem访问8)系统不需要考虑文件访问的互斥等问题方案l)create系统调用
1.根据传入的fileAddress,从虚拟内存中读出文件名
2.判断文件名是否存在,即和eAddress处是否有文件名
3.如果不存在,直接创建先去找合适的位置,如果已经有大于16个,退出,否则创建,创建只需调用filesystem的open即可(传入的布尔值create为true)2)open系统调用
1.根据传入的fileAddress,从虚拟内存中读出文件名
2.判断文件名是否存在,即fileAddress处是否有文件名
3.先去找合适的位置,如果已经有大于16个,退出,否则创建只需调用filesystem的open即可传入的布尔值create为false
4.维护本地描述符表3read系统调用Read系统调用的三个参数依次为文件描述符,写入的内存地址,读取的字节数在Read系统调用中进行如下操作
1.如果打开文件大于16个或者小于0个,或者打开文件列表为空,直接返回
2.创建数组temp,把文件内容读入temp,求出读出数据长度
3.若读出数据小于即为出错,返回
4.把该数据写入虚拟内存
5.返回写入内存的字节数4write系统调用Write系统调用的三个参数依次为文件描述符,读内存的地址,写入文件的字节数在Write系统调用中进行如下操作
1.如果打开文件大于16个或者小于0个,或者打开文件列表为空,直接返回
2.创建数组temp,把虚拟内存中的内容读入temp,得到读出数据长度3,若读出数据小于即为出错,返回
4.把该数据写入磁盘
5.若写的数据长度小于读出的数据长度,则错误,返回错误代码5close系统调用Close系统调用的唯一一个参数为文件描述符在Close系统调用中进行如下操作
1.如果打开文件大于16个或者小于0个,或者打开文件列表为空,直接返回
2.如果不存在,关闭出错
3.否则关闭,把openfile数组中fileDescriptor中的位置置为06unlink系统调用:
1.根据传入的fileAddress,从虚拟内存中读出文件名
2.如果不存在,不必删除
3.如果存在,就删除,出错返回错误代码一般地,在Unlink调用中只需读取文件名并执行fileSystem.remove方法删除文件即可但是,一个文件可能被多个进程打开而不能立即删除,必须等所有打开这个文件的进程都关闭该文件后才能删除因此,在Close系统调用中还要增加如下内容若文件关闭后它在全局文件表中已经不存在且文件名在删除队列中,则此时执行删除文件操作,并将文件从删除队列中移出L L3关键点与难点注意以上系统调用只是在一般情况下函数的执行流程为了提高系统的健壮性,在系统调用中还要进行下列错误检查a文件名长度不得超过256字符,不得含有非法字符或空b打开,创建文件时,局部描述符表不能满cfileSystem的操作返回值必须正确dreadVirtualMemory和writeVirtualMemory的返[II值必须正确
1.
1.4实现代码private inthand IeCreateint fiI eAddress{//限定文件名长度,readV irtuaI Memorystring读取文件名String fiIename=readV irtuaIMemoryStr ing f iI eAddress,256;if fiIename==null return-1;int fiIeDescriptor=f indEmpty:if fiIeDescriptor==-1return-1;else//ThreadedKernel.fiI eSystem.open打开文件第二个参数为true表示创建新文件openfiIe fileDescr iptor]:ThreadedKernel fiIeSystem openfiIename.true;return fileDescriptor;private inthand IeOpen intfiI eAddress〃限定文件名长度String fiIename readVirtuaIMemoryStr ingfiI eAddress,256;if fiIename==null return-1;int fileDescriptor=findEmpty0://为空,报错if fileDescriptor==-1return-1;else{openf iIeIf iIeDescr i ptor]二ThreadedKernel fiI eSystemopenfilename,false;return fileDescriptor;private inthand IeReadint fileDescriptor,int bufferAddress,int length{//如果打开文件大于16个或者小于0个,或者打开文件列表为空,直接返回if fileDescriptor1511fileDescriptor0openf iIe[f iIeDescri ptor]==null return-1;byte temp]=new byte[length];//通过OpenFi Ie.read读取文件内容int readNumber=openf iIefiIeDescr iptorread temp.0length;if readNumber=0return0;//把该数据写入虚拟内存int writeNumber=wr iteVi rtuaI Memory bufferAddress,temp;return writeNumber;private inthandleWriteint fiIeDescriptor,int bufferAddress.int length//如果打开文件大于16个或者小于个,或者打开文件列表为空,直接返回if fiIeDescriptor1511fiIeDescriptor011openf iIe[f iIeDescri ptor]==null return-1://文件未打开,出错//创建数组逾眩,把虚拟内存中的内容读入鲍电得到读出数据长度byte temp[]二new byte[length];int readNumber=readV irtuaIMemorybufferAddress,temp;//若读出数据小于0即为出错,返回if readNumber=0return0;//把该数据写入磁盘int writeNumber=openfiIe[fiIeDescriptor].writetemp.0length;//若写的数据长度小于读出的数据长度,则错误,返向错误代码if writeNumberlength return-1;//返回写入文件的字节数return writeNumber;private inthand IeClose intfiIeDescr iptor{//如果打开文件大于16个或者小于0个,或者打开文件列表为空,直接返回if fiIeDescriptor1511fiIeDescriptor011openf iIe[f iIeDescri ptor]==null//文件不存在,关闭出错return-1;//否则关闭,把迪正L怆数组中fileDescriptor中的位置置为0openfileLfiIeDescriptor.close;openf iIe[fiIeDescriptor]=null;return0;private inthand IeUn Iink intfiI eAddress//根据传入的fileAddress,从虚拟内存中读出文件名String fiIename=readVirtuaIMemoryString fiIeAddress,256;//如果不存在,不必删除if fiIename==null return0//如果存在,就删除,出错返回错误代码if ThreadedKernelfiI eSystemremove filename return0else return-1;
11.2Task
2.2完成对多道程序的支持121题目要求完成对多道程序的支持已给出的代码只能一次运行一个进程,而你要使它支持多道程序从分配物理内存入手,不同的进程在在内存使用上不会重叠用户程序不会使用malloc或free,既用户没有动态内存分配的需求也就是说当进程创建,你完全知道它需要的内存大小,你要为进程栈分配合适的页大小,8页就足够了建议保持空闲物理页的全局链接列表UserKernel class的一部分,访问列表时会用到同步解决方案为新进程分配页时务必有效的使用内存只在连续块上分配内存是不可取的的,你的方案必须用到空闲内存池中的缝隙保持每个进程的页表,页表保持了用户虚拟地址到物理地址的映射TranslationEntry class代表了一个虚拟到物理的页转换如果页来自COFF section,那么在TranslationEntry.readOnly文件中要将其标记。