操作系统课程设计实验报告Word格式文档下载.docx
- 文档编号:20979076
- 上传时间:2023-01-26
- 格式:DOCX
- 页数:19
- 大小:156.14KB
操作系统课程设计实验报告Word格式文档下载.docx
《操作系统课程设计实验报告Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计实验报告Word格式文档下载.docx(19页珍藏版)》请在冰豆网上搜索。
8)系统不需要考虑文件访问的互斥等问题。
方案:
1)create系统调用:
1.根据传入的,从虚拟内存中读出文件名
2.判断文件名是否存在,即处是否有文件名
3.如果不存在,直接创建。
先去找合适的位置,如果已经有大于16个,退出,否则创建,创建只需调用的open即可(传入的布尔值create为true)
2)open系统调用:
1.根据传入的,从虚拟内存中读出文件名
3.先去找合适的位置,如果已经有大于16个,退出,否则创建只需调用的open即可(传入的布尔值create为false)
4.维护本地描述符表
3)read系统调用
Read系统调用的三个参数依次为:
文件描述符,写入的内存地址,读取的字节数。
在Read系统调用中进行如下操作:
1.如果打开文件大于16个或者小于0个,或者打开文件列表为空,直接返回。
2.创建数组temp,把文件内容读入temp,求出读出数据长度
3.若读出数据小于0即为出错,返回。
4.把该数据写入虚拟内存。
5.返回写入内存的字节数
4)write系统调用
Write系统调用的三个参数依次为:
文件描述符,读内存的地址,写入文件的字节数。
在Write系统调用中进行如下操作:
2.创建数组temp,把虚拟内存中的内容读入temp,得到读出数据长度3.若读出数据小于0即为出错,返回。
4.把该数据写入磁盘。
5.若写的数据长度小于读出的数据长度,则错误,返回错误代码
5)close系统调用
Close系统调用的唯一一个参数为文件描述符。
在Close系统调用中进行如下操作:
2.如果不存在,关闭出错
3.否则关闭,把openfile数组中中的位置置为0
6)unlink系统调用:
1.根据传入的,从虚拟内存中读出文件名。
2.如果不存在,不必删除
3.如果存在,就删除,出错返回错误代码
一般地,在Unlink调用中只需读取文件名并执行方法删除文件即可。
但是,一个文件可能被多个进程打开而不能立即删除,必须等所有打开这个文件的进程都关闭该文件后才能删除。
因此,在Close系统调用中还要增加如下内容:
若文件关闭后它在全局文件表中已经不存在且文件名在删除队列中,则此时执行删除文件操作,并将文件从删除队列中移出。
1.1.3关键点与难点
注意:
以上系统调用只是在一般情况下函数的执行流程。
为了提高系统的健壮性,在系统调用中还要进行下列错误检查:
a)文件名长度不得超过256字符,不得含有非法字符或空。
b)打开,创建文件时,局部描述符表不能满。
c)的操作返回值必须正确。
d)readVirtualMemory和writeVirtualMemory的返回值必须正确。
1.1.4实现代码
privateinthandleCreate(int){
//限定文件名长度,readVirtualMemoryString读取文件名
String=readVirtualMemoryString(,256);
if(==null)
return-1;
int=findEmpty();
if(==-1)
else{
//ThreadedKernel.()打开文件(第二个参数为true表示创建新文件)
openfile[]=ThreadedKernel..open(,
true);
return;
}
}
privateinthandleOpen(int){
//限定文件名长度
//为空,报错。
openfile[]=ThreadedKernel..open(,
false);
return;
privateinthandleRead(int,intbufferAddress,intlength){
//如果打开文件大于16个或者小于0个,或者打开文件列表为空,直接返回。
if(>
15||<
0
||openfile[]==null)
bytetemp[]=newbyte[length];
//通过Open读取文件内容
intreadNumber=openfile[].read(temp,0,length);
if(readNumber<
=0)
return0;
//把该数据写入虚拟内存。
intwriteNumber=writeVirtualMemory(bufferAddress,temp);
returnwriteNumber;
privateinthandleWrite(int,intbufferAddress,intlength){
//文件未打开,出错
//创建数组temp,把虚拟内存中的内容读入temp,得到读出数据长度
bytetemp[]=newbyte[length];
intreadNumber=readVirtualMemory(bufferAddress,temp);
//若读出数据小于0即为出错,返回。
if(readNumber<
//把该数据写入磁盘。
intwriteNumber=openfile[].write(temp,0,length);
//若写的数据长度小于读出的数据长度,则错误,返回错误代码
if(writeNumber<
length)
//返回写入文件的字节数
privateinthandleClose(int){
//文件不存在,关闭出错
//否则关闭,把openfile数组中中的位置置为0
openfile[].close();
openfile[]=null;
return0;
privateinthandleUnlink(int){
//根据传入的,从虚拟内存中读出文件名。
//如果不存在,不必删除
//如果存在,就删除,出错返回错误代码
if(ThreadedKernel..remove())
else
1.2Task
2.2完成对多道程序的支持
1.2.1题目要求
完成对多道程序的支持。
已给出的代码只能一次运行一个进程,而你要使它支持多道程序。
从分配物理内存入手,不同的进程在在内存使用上不会重叠。
用户程序不会使用malloc()或free(),既用户没有动态内存分配的需求。
也就是说当进程创建,你完全知道它需要的内存大小,你要为进程栈分配合适的页大小,8页就足够了。
建议保持空闲物理页的全局链接列表(UserKernelclass的一部分),访问列表时会用到同步。
解决方案为新进程分配页时务必有效的使用内存。
只在连续块上分配内存是不可取的的,你的方案必须用到空闲内存池中的缝隙。
保持每个进程的页表,页表保持了用户虚拟地址到物理地址的映射。
TranslationEntryclass代表了一个虚拟到物理的页转换。
如果页来自COFFsection,那么在TranslationEntry.readOnly文件中要将其标记为只读。
这个方法失败不会抛出异常,它总会返回传送的位数,即使是零。
修改UserProcess.loadSections(),根据所需为进程分配页数。
用你决定的分配规则。
这个方法还要为进程开启页表structure,这样进程就被加载到当前物理内存页中。
1.2.2题目分析与实现方案
Nachos为不同进程应分配完全不同的物理内存,但不支持动态内存分配,所以需要分配的内存在装入程序时就可以确定了(代码,数据,堆栈部分)。
故在装入程序时就为每个进程一次性分配固定的物理内存,在进程结束时收回它们。
这里还需要实现如下简单的虚拟内存方案:
每个进程的地址空间是连续的虚拟内存,但这些连续的虚拟页面在物理内存中却不一定是连续的。
这个方案的简单之处在于,虚拟空间的总容量和物理空间的总容量相等,映射机制只是从虚拟内存到物理内存的一一映射。
除了内存的分配,内存的读写也要体现出映射机制。
页表pageTable以虚拟页号为下标,其中的每个项目是一个machine.TranslationEntry类型的对象,存放了一个页的下列信息:
物理页号,虚拟页号,是否有效,是否只读,是否被用过,是否脏。
在UserKernel中定义一个全局队列memoryLinkedList用于存放当前空闲的物理页号,一个保护内存互斥访问的锁allocateMemoryLock。
开始时,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:
//保护内存互斥访问的锁
publicstaticLockallocateMemoryLock;
//全局队列,用于存放当前空闲的物理页号
publicstaticLinkedList<
Integer>
memoryLinkedList;
UserProcess:
protectedbooleanloadSections(){
//获取分配内存的锁,锁定内存
UserKernel.allocateMemoryLock.acquire();
//判断能否装载
if(numPages>
UserKernel.memoryLinkedList.size()){
coff.close();
Lib.debug(dbgProcess,"
\tinsufficientphysicalmemory"
);
UserKernel.allocateMemoryLock.release();
//返回装载失败
returnfalse;
//创建页表
pageTable=newTranslationEntry[numPages];
for(inti=0;
i<
numPages;
i++){
intnextPage=UserKernel.memoryLinkedList.remove();
pageTable[i]=newTranslationEntry(i,nextPage,true,false,
false,false);
//释放锁
UserKernel.allocateMemoryLock.release();
for(ints=0;
s<
coff.getNumSections();
s++){
CoffSectionsection=coff.getSection(s);
//获得section
\tinitializing"
+section.getName()
+"
section("
+section.getLength()+"
pages)"
for(inti=0;
section.getLength();
intvpn=section.getFirstVPN()+i;
//标记只为已读
pageTable[vpn].readOnly=section.isReadOnly();
section.loadPage(i,pageTable[vpn].ppn);
}
returntrue;
publicintreadVirtualMemory(intvaddr,byte[]data,intoffset,intlength){
//保证偏移量与长度都为正,偏移量+长度<
=总的数据长度
Lib.assertTrue(offset>
=0&
&
length>
=0
&
offset+length<
=data.length);
byte[]memory=Machine.processor().getMemory();
//获得需求
if(length>
(pageSize*numPages-vaddr))//判断能否读取
length=pageSize*numPages-vaddr;
if(data.length-offset<
length=data.length-offset;
inttransferredbyte=0;
do{
intpageNum=Processor.pageFromAddress(vaddr+transferredbyte);
if(pageNum<
0||pageNum>
=pageTable.length)
return0;
intpageOffset=Processor.offsetFromAddress(vaddr
+transferredbyte);
intleftByte=pageSize-pageOffset;
intamount=Math.min(leftByte,length-transferredbyte);
intrealAddress=pageTable[pageNum].ppn*pageSize+pageOffset;
System.arraycopy(memory,realAddress,data,offset
+transferredbyte,amount);
transferredbyte=transferredbyte+amount;
}while(transferredbyte<
length);
returntransferredbyte;
}
publicintwriteVirtualMemory(intvaddr,byte[]data,intoffset,intlength){
(pageSize*numPages-vaddr))
System.arraycopy(data,offset+transferredbyte,memory,
realAddress,amount);
1.3
Task
2.3
实现系统调用
1.3.1题目要求
实现系统调用(exec,join,andexit,同样在syscall.h)。
此外,所有通过寄存器来Exec和加入的地址是虚拟地址。
你应该使用readVirtualMemory和readVirtualMemoryString在内核和用户进程之间传递内存。
同样,你必须防止这些系统调用。
注意,子过程的状态是进程完全私有的。
这意味着,父进
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 课程设计 实验 报告