操作系统实验Synchronization Using Semaphores.docx
《操作系统实验Synchronization Using Semaphores.docx》由会员分享,可在线阅读,更多相关《操作系统实验Synchronization Using Semaphores.docx(47页珍藏版)》请在冰豆网上搜索。
操作系统实验SynchronizationUsingSemaphores
计算机科学与技术学院实验报告
实验题目:
操作系统课程设计
学号:
硬件环境和软件环境:
Linux操作系统和Nachos,Mips,GDB
实验三:
SynchronizationUsingSemaphores
实验目的:
1,理解如何实施Nachos的信号量,以及如何在生产者/消费者问题是通过使用信号量。
2,了解如何创建Nachos并发线程。
3,知道如何测试和调试程序。
实验代码:
#include
#include"copyright.h"
#include"system.h"
#include"synch.h"
#include"ring.h"
#defineBUFF_SIZE3//thesizeoftheroundbuffer
#defineN_PROD2//thenumberofproducers
#defineN_CONS2//thenumberofconsumers
#defineN_MESSG4//thenumberofmessagesproducedbyeachproducer
#defineMAX_NAME16//themaximumlenghofaname
#defineMAXLEN48
#defineLINELEN24
Thread*producers[N_PROD];//arrayofpointerstotheproducer
Thread*consumers[N_CONS];//andconsumerthreads;
charprod_names[N_PROD][MAX_NAME];//arrayofcharaterstringforprodnames
charcons_names[N_CONS][MAX_NAME];//arrayofcharaterstringforconsnames
Semaphore*nempty,*nfull;//twosemaphoresforemptyandfullslots
Semaphore*mutex;//semaphoreforthemutualexclusion
Ring*ring;
//----------------------------------------------------------------------
//Producer
//LoopN_MESSGtimesandproduceamessageandputitinthe
//sharedringbuffereachtime.
//"which"issimplyanumberidentifyingtheproducerthread.
void
Producer(_intwhich)
{
intnum;
slot*message=newslot(0,0);
//ThisloopistogenerateN_MESSGmessagestoputintotoringbuffer
//bycallingring->Put(message).Eachmessagecarriesamessageid
//whichisrepresenedbyinteger"num".Thismessageidshouldbeput
//into"value"fieldoftheslot.Itshouldalsocarrytheid
//oftheproducerthreadtobestoredin"thread_id"fieldsothat
//consumerthreadscanknowwhichproducergeneratesthemessagelater
//on.Youneedtoputsynchronizationcode
//beforeandafterthecallring->Put(message).Seethealgorithmsin
//page182ofthetextbook.
for(num=0;num//Putthecodetopreparethemessagehere.message->thread_id=which;//生产者线程编号message->value=num;//生产的massage的编号//Putthecodeforsynchronizationbeforering->Put(message)here.//...nempty->P();//查看buffer是否为空,若为空则buffer--mutex->P();//加锁,互斥ring->Put(message);//Putthecodeforsynchronizationafterring->Put(message)here.mutex->V();//解锁nfull->V();//空buffer数量加1}}//----------------------------------------------------------------------//Consumer//endlesslooptofetchmessagesfromtheringbufferand//recordthesemessageinthecorrespondingfile.////----------------------------------------------------------------------voidConsumer(_intwhich){charstr[MAXLEN];charfname[LINELEN];intfd;slot*message=newslot(0,0);//toformaoutputfilenameforthisconsumerthread.//allthemessagesreceivedbythisconsumerwillberecordedin//thisfile.sprintf(fname,"tmp_%d",which);//创建文件,以消费者编号为文件名//createafile.NotethatthisisaUNIXsystemcall.if((fd=creat(fname,0600))==-1){perror("creat:filecreatefailed");Exit(1);//exit(1)不识别,Exit可以执行}for(;;){//Putthecodeforsynchronizationbeforering->Get(message)here.//...nfull->P();//检查buffer中是否有massagemutex->P();//加锁,形成进程间互斥ring->Get(message);//Putthecodeforsynchronizationafterring->Get(message)here.//...mutex->V();//解除互斥nempty->V();//对nempty++//formastringtorecordthemessagesprintf(str,"producerid-->%d;Messagenumber-->%d;\n",message->thread_id,message->value);//向文件中打印读取信息的情况//writethisstringintotheoutputfileofthisconsumer.//notethatthisisanotherUNIXsystemcall.if(write(fd,str,strlen(str))==-1){perror("write:writefailed");Exit(1);}}}//----------------------------------------------------------------------//ProdCons//Setupsemaphoresforsharedroundbufferand//createandforkproducersandconsumerthreads//----------------------------------------------------------------------voidProdCons(){inti;DEBUG('t',"EnteringProdCons");//Putthecodetoconstructallthesemaphoreshere.//初始化信号量mutex=newSemaphore("mutux",1);//互斥信号量初始为1nfull=newSemaphore("full",0);//未被取走的massage数量nempty=newSemaphore("empty",BUFF_SIZE);//buffer的总数量//Putthecodetoconstructaringbufferobjectwithsize//BUFF_SIZEhere.//...ring=newRing(BUFF_SIZE);//createandforkN_PRODofproducerthreadsfor(i=0;i{//thisstatemetistoformastringtobeusedasthenamefor//produderi.sprintf(prod_names[i],"producer_%d",i);//Putthecodetocreateandforkanewproducerthreadusing//thenameinprod_names[i]and//integeriastheargumentoffunction"Producer"producers[i]=newThread(prod_names[i]);//创建生产者线程producers[i]->Fork(Producer,i);};//createandforkN_CONSofconsumerthreadsfor(i=0;i{//thisstatemetistoformastringtobeusedasthenamefor//consumeri.sprintf(cons_names[i],"consumer_%d",i);//Putthecodetocreateandforkanewconsumerthreadusing//thenameincons_names[i]and//integeriastheargumentoffunction"Consumer"consumers[i]=newThread(cons_names[i]);//创建消费者线程consumers[i]->Fork(Consumer,i);};}P操作://////对信号量进行加锁voidSemaphore::P(){IntStatusoldLevel=interrupt->SetLevel(IntOff);//disableinterruptswhile(value==0){//semaphorenotavailablequeue->Append((void*)currentThread);//sogotosleepcurrentThread->Sleep();}Value--;//semaphoreavailable,//consumeitsvalue(void)interrupt->SetLevel(oldLevel);//re-enableinterrupts}V操作:////////对信号量进行解锁voidSemaphore::V(){Thread*thread;IntStatusoldLevel=interrupt->SetLevel(IntOff);thread=(Thread*)queue->Remove();if(thread!=NULL)//makethreadready,consumingtheVimmediatelyscheduler->ReadyToRun(thread);value++;(void)interrupt->SetLevel(oldLevel);} 实验五:ExtendableFiles实验目的:1,本实验室会议的目的是帮助你开始工作,扩大Nachos文件系统。 2,我们特别希望新的Nachos,文件系统具有以下功能:当一个文件被创建,它的初始大小可以设置为0。 3,文件的大小可以增加,如果更多的数据被写入文件。 实验分析以及主要代码:由于要对文件系统进行修改,首先需要明白其文件的存储结构。nachos和unix有较大的差别,通过查阅资料具体表现在一下方面:1.在磁盘的组织结构方面Nachos中文件同样有其inode和一般存储磁盘块,即Nachos物理磁盘的扇区。但是它不象UNIX一样,将文件系统中所有文件的inode存放在一起,即inode区中。每个Nachos文件的inode占用一个单独的扇区,分散在物理磁盘的任何地方,同一般存储扇区用同样的方式进行申请和回收。它没有文件系统管理块,是通过位图(Bitmap)来管理整个磁盘上的空闲块。2.在文件系统空闲磁盘数据块和inode块管理方面Nachos中有一个特殊的文件,即位图文件。该文件存放的是整个文件系统的扇区使用情况的位图。如果一个扇区为空闲,则它在位图文件相应的位为0,否则为1。Nachos中没有专门对inode扇区进行管理。当需要申请一个扇区时,根据位图文件寻找一个空闲的扇区,并将其相应的位置为1。当释放一个扇区时,将位图中相应的位置为0。位图文件是一个临界资源,应该互斥访问。现有的文件系统没有实现互斥访问,所以每次只允许一个线程访问文件系统。位图文件的inode占据0号扇区。3.在文件系统的目录管理方面一般的文件系统都采用树状目录结构,有的UNIX文件系统还有目录之间的勾连,形成图状文件系统结构。Nachos则比较简单,只有一级目录,也就是只有根目录,所有的文件都在根目录下。而且根目录中可以存放的文件数是有限的。Nachos文件系统的根目录同样也是通过文件方式存放的,它的inode占据了1号扇区。4.文件的索引结构上Nachos同一般的UNIX一样,采用索引表进行物理地址和逻辑地址之间的转换,索引表存放在文件的inode中。但是目前Nachos采用的索引都是直接索引,所以Nachos的最大文件长度不能大于4K。5.Nachos文件系统除了在以上几点上有所不足外,还有以下一些不完善的地方:●必须在文件生成时创建索引表。所以Nachos在创建一个文件时,必须给出文件的大小;而且当文件生成后,就不能改变文件的大小。●目前该文件系统没有Cache机制●目前文件系统的健壮性不够强。当正在使用文件系统时,如果突然系统中断,文件系统中的内容可能不保证正确。在Nachos文件系统中,许多数据结构既可存放在宿主机内存里,又可存放在磁盘上。为了一致起见,文件系统中Synchdisk以上的类都有一个FetchFrom成员方法,它把数据结构从磁盘读到内存;还有一个WriteBack成员方法,与FetchFrom相反,它把数据结构从内存写回磁盘。在内存中的数据结构与磁盘上的完全一致,这给管理带来了不少方便。1.同步磁盘分析(文件synchdisk.cc、synchdisk.h)和其它设备一样,Nachos模拟的磁盘是异步设备。当发出访问磁盘的请求后立刻返回,当从磁盘读出或写入数据结束后,发出磁盘中断,说明一次磁盘访问真正结束。Nachos是一个多线程的系统,如果多个线程同时对磁盘进行访问,会引起系统的混乱。所以必须作出这样的限制:●同时只能有一个线程访问磁盘●当发出磁盘访问请求后,必须等待访问的真正结束。这两个限制就是实现同步磁盘的目的。SynchDisk的类定义和实现如下所示:classSynchDisk{public:SynchDisk(char*name);//生成一个同步磁盘~SynchDisk();//析构方法voidReadSector(intsectorNumber,char*data);//同步读写磁盘,只有当真正读写完毕voidWriteSector(intsectorNumber,char*data);//后返回voidRequestDone();//磁盘中断处理时调用private:Disk*disk;//物理异步磁盘设备Semaphore*semaphore;//控制读写磁盘返回的信号量Lock*lock;//控制只有一个线程访问的锁};以ReadSector为例来说明同步磁盘的工作机制:voidSynchDisk::ReadSector(intsectorNumber,char*data){lock->Acquire();//加锁(一次只允许一个线程访问磁盘)disk->ReadRequest(sectorNumber,data);//对磁盘进行读访问请求semaphore->P();//等待磁盘中断的到来lock->Release();//解锁(访问结束)}当线程向磁盘设备发出读访问请求后,等待磁盘中断的到来。一旦磁盘中断来到,中断处理程序执行semaphore->V()操作,ReadSector得以继续运行。对磁盘同步写也基于同样的原理。2.位图模块分析(文件bitmap.cc、bitmap.h)在Nachos的文件系统中,是通过位图来管理空闲块的。Nachos的物理磁盘是以扇区为访问单位的,将扇区从0开始编号。所谓位图管理,就是将这些编号填入一张表,表中为0的地方说明该扇区没有被占用,而非0位置说明该扇区已被占用。这部分内容是用BitMap类实现的。BitMap类的实现比较简单,这里只是介绍其接口。classBitMap{public:BitMap(intnitems);//初始化方法,给出位图的大小,将所有位标明未用~BitMap();//析构方法voidMark(intwhich);//标志第which位被占用voidClear(intwhich);//清除第which位boolTest(intwhich);//测试第which位是否被占用,若是,返回TRUEintFind();//找到第一个未被占用的位,标志其被占用;//若没有找到,返回-1intNumClear();//返回多少位没有被占用voidPrint();//打印出整个位图(调试用)voidFetchFrom(OpenFile*file);//从一个文件中读出位图voidWriteBack(OpenFile*file);//将位图内容写入文件private:...//内部实现属性};3.文件系统模块分析(文件filesys.cc、filesys.h)读者在增强了线程管理的功能后,可以同时开展文件系统部分功能的增强或实现虚拟内存两部分工作。在Nachos中,实现了两套文件系统,它们对外接口是完全一样的:一套称作为FILESYS_STUB,它是建立在UNIX文件系统之上的,而不使用Nachos的模拟磁盘,它主要用于读者先实现了用户程序和虚拟内存,然后再着手增强文件系统的功能;另一套是Nachos的文件系统,它是实现在Nachos的虚拟磁盘上的。当整个系统完成之后,只能使用第二套文件系统的实现。以下我们只分析在Nachos文件系统的实现:classFileSystem{public:FileSystem(boolformat);//生成方法boolCreate(char*name,intinitialSize);//生成一个文件OpenFile*Open(char*name);//打开一个文件boolRemove(char*name);//删除一个文件voidList();//列出文件系统中所有的文件//(实际上就是根目录中所有的文件)voidPrint();//列出文件系统中所有的文件和它
//Putthecodetopreparethemessagehere.
message->thread_id=which;//生产者线程编号
message->value=num;//生产的massage的编号
//Putthecodeforsynchronizationbeforering->Put(message)here.
//...
nempty->P();//查看buffer是否为空,若为空则buffer--
mutex->P();//加锁,互斥
ring->Put(message);
//Putthecodeforsynchronizationafterring->Put(message)here.
mutex->V();//解锁
nfull->V();//空buffer数量加1
}
//Consumer
//endlesslooptofetchmessagesfromtheringbufferand
//recordthesemessageinthecorrespondingfile.
//
Consumer(_intwhich)
charstr[MAXLEN];
charfname[LINELEN];
intfd;
//toformaoutputfilenameforthisconsumerthread.
//allthemessagesreceivedbythisconsumerwillberecordedin
//thisfile.
sprintf(fname,"tmp_%d",which);//创建文件,以消费者编号为文件名
//createafile.NotethatthisisaUNIXsystemcall.
if((fd=creat(fname,0600))==-1)
perror("creat:
filecreatefailed");
Exit
(1);//exit
(1)不识别,Exit可以执行
for(;;){
//Putthecodeforsynchronizationbeforering->Get(message)here.
nfull->P();//检查buffer中是否有massage
mutex->P();//加锁,形成进程间互斥
ring->Get(message);
//Putthecodeforsynchronizationafterring->Get(message)here.
mutex->V();//解除互斥
nempty->V();//对nempty++
//formastringtorecordthemessage
sprintf(str,"producerid-->%d;Messagenumber-->%d;\n",message->thread_id,message->value);
//向文件中打印读取信息的情况
//writethisstringintotheoutputfileofthisconsumer.
//notethatthisisanotherUNIXsystemcall.
if(write(fd,str,strlen(str))==-1){
perror("write:
writefailed");
(1);
//ProdCons
//Setupsemaphoresforsharedroundbufferand
//createandforkproducersandconsumerthreads
ProdCons()
inti;
DEBUG('t',"EnteringProdCons");
//Putthecodetoconstructallthesemaphoreshere.
//初始化信号量
mutex=newSemaphore("mutux",1);//互斥信号量初始为1
nfull=newSemaphore("full",0);//未被取走的massage数量
nempty=newSemaphore("empty",BUFF_SIZE);//buffer的总数量
//Putthecodetoconstructaringbufferobjectwithsize
//BUFF_SIZEhere.
ring=newRing(BUFF_SIZE);
//createandforkN_PRODofproducerthreads
for(i=0;i{//thisstatemetistoformastringtobeusedasthenamefor//produderi.sprintf(prod_names[i],"producer_%d",i);//Putthecodetocreateandforkanewproducerthreadusing//thenameinprod_names[i]and//integeriastheargumentoffunction"Producer"producers[i]=newThread(prod_names[i]);//创建生产者线程producers[i]->Fork(Producer,i);};//createandforkN_CONSofconsumerthreadsfor(i=0;i{//thisstatemetistoformastringtobeusedasthenamefor//consumeri.sprintf(cons_names[i],"consumer_%d",i);//Putthecodetocreateandforkanewconsumerthreadusing//thenameincons_names[i]and//integeriastheargumentoffunction"Consumer"consumers[i]=newThread(cons_names[i]);//创建消费者线程consumers[i]->Fork(Consumer,i);};}P操作://////对信号量进行加锁voidSemaphore::P(){IntStatusoldLevel=interrupt->SetLevel(IntOff);//disableinterruptswhile(value==0){//semaphorenotavailablequeue->Append((void*)currentThread);//sogotosleepcurrentThread->Sleep();}Value--;//semaphoreavailable,//consumeitsvalue(void)interrupt->SetLevel(oldLevel);//re-enableinterrupts}V操作:////////对信号量进行解锁voidSemaphore::V(){Thread*thread;IntStatusoldLevel=interrupt->SetLevel(IntOff);thread=(Thread*)queue->Remove();if(thread!=NULL)//makethreadready,consumingtheVimmediatelyscheduler->ReadyToRun(thread);value++;(void)interrupt->SetLevel(oldLevel);} 实验五:ExtendableFiles实验目的:1,本实验室会议的目的是帮助你开始工作,扩大Nachos文件系统。 2,我们特别希望新的Nachos,文件系统具有以下功能:当一个文件被创建,它的初始大小可以设置为0。 3,文件的大小可以增加,如果更多的数据被写入文件。 实验分析以及主要代码:由于要对文件系统进行修改,首先需要明白其文件的存储结构。nachos和unix有较大的差别,通过查阅资料具体表现在一下方面:1.在磁盘的组织结构方面Nachos中文件同样有其inode和一般存储磁盘块,即Nachos物理磁盘的扇区。但是它不象UNIX一样,将文件系统中所有文件的inode存放在一起,即inode区中。每个Nachos文件的inode占用一个单独的扇区,分散在物理磁盘的任何地方,同一般存储扇区用同样的方式进行申请和回收。它没有文件系统管理块,是通过位图(Bitmap)来管理整个磁盘上的空闲块。2.在文件系统空闲磁盘数据块和inode块管理方面Nachos中有一个特殊的文件,即位图文件。该文件存放的是整个文件系统的扇区使用情况的位图。如果一个扇区为空闲,则它在位图文件相应的位为0,否则为1。Nachos中没有专门对inode扇区进行管理。当需要申请一个扇区时,根据位图文件寻找一个空闲的扇区,并将其相应的位置为1。当释放一个扇区时,将位图中相应的位置为0。位图文件是一个临界资源,应该互斥访问。现有的文件系统没有实现互斥访问,所以每次只允许一个线程访问文件系统。位图文件的inode占据0号扇区。3.在文件系统的目录管理方面一般的文件系统都采用树状目录结构,有的UNIX文件系统还有目录之间的勾连,形成图状文件系统结构。Nachos则比较简单,只有一级目录,也就是只有根目录,所有的文件都在根目录下。而且根目录中可以存放的文件数是有限的。Nachos文件系统的根目录同样也是通过文件方式存放的,它的inode占据了1号扇区。4.文件的索引结构上Nachos同一般的UNIX一样,采用索引表进行物理地址和逻辑地址之间的转换,索引表存放在文件的inode中。但是目前Nachos采用的索引都是直接索引,所以Nachos的最大文件长度不能大于4K。5.Nachos文件系统除了在以上几点上有所不足外,还有以下一些不完善的地方:●必须在文件生成时创建索引表。所以Nachos在创建一个文件时,必须给出文件的大小;而且当文件生成后,就不能改变文件的大小。●目前该文件系统没有Cache机制●目前文件系统的健壮性不够强。当正在使用文件系统时,如果突然系统中断,文件系统中的内容可能不保证正确。在Nachos文件系统中,许多数据结构既可存放在宿主机内存里,又可存放在磁盘上。为了一致起见,文件系统中Synchdisk以上的类都有一个FetchFrom成员方法,它把数据结构从磁盘读到内存;还有一个WriteBack成员方法,与FetchFrom相反,它把数据结构从内存写回磁盘。在内存中的数据结构与磁盘上的完全一致,这给管理带来了不少方便。1.同步磁盘分析(文件synchdisk.cc、synchdisk.h)和其它设备一样,Nachos模拟的磁盘是异步设备。当发出访问磁盘的请求后立刻返回,当从磁盘读出或写入数据结束后,发出磁盘中断,说明一次磁盘访问真正结束。Nachos是一个多线程的系统,如果多个线程同时对磁盘进行访问,会引起系统的混乱。所以必须作出这样的限制:●同时只能有一个线程访问磁盘●当发出磁盘访问请求后,必须等待访问的真正结束。这两个限制就是实现同步磁盘的目的。SynchDisk的类定义和实现如下所示:classSynchDisk{public:SynchDisk(char*name);//生成一个同步磁盘~SynchDisk();//析构方法voidReadSector(intsectorNumber,char*data);//同步读写磁盘,只有当真正读写完毕voidWriteSector(intsectorNumber,char*data);//后返回voidRequestDone();//磁盘中断处理时调用private:Disk*disk;//物理异步磁盘设备Semaphore*semaphore;//控制读写磁盘返回的信号量Lock*lock;//控制只有一个线程访问的锁};以ReadSector为例来说明同步磁盘的工作机制:voidSynchDisk::ReadSector(intsectorNumber,char*data){lock->Acquire();//加锁(一次只允许一个线程访问磁盘)disk->ReadRequest(sectorNumber,data);//对磁盘进行读访问请求semaphore->P();//等待磁盘中断的到来lock->Release();//解锁(访问结束)}当线程向磁盘设备发出读访问请求后,等待磁盘中断的到来。一旦磁盘中断来到,中断处理程序执行semaphore->V()操作,ReadSector得以继续运行。对磁盘同步写也基于同样的原理。2.位图模块分析(文件bitmap.cc、bitmap.h)在Nachos的文件系统中,是通过位图来管理空闲块的。Nachos的物理磁盘是以扇区为访问单位的,将扇区从0开始编号。所谓位图管理,就是将这些编号填入一张表,表中为0的地方说明该扇区没有被占用,而非0位置说明该扇区已被占用。这部分内容是用BitMap类实现的。BitMap类的实现比较简单,这里只是介绍其接口。classBitMap{public:BitMap(intnitems);//初始化方法,给出位图的大小,将所有位标明未用~BitMap();//析构方法voidMark(intwhich);//标志第which位被占用voidClear(intwhich);//清除第which位boolTest(intwhich);//测试第which位是否被占用,若是,返回TRUEintFind();//找到第一个未被占用的位,标志其被占用;//若没有找到,返回-1intNumClear();//返回多少位没有被占用voidPrint();//打印出整个位图(调试用)voidFetchFrom(OpenFile*file);//从一个文件中读出位图voidWriteBack(OpenFile*file);//将位图内容写入文件private:...//内部实现属性};3.文件系统模块分析(文件filesys.cc、filesys.h)读者在增强了线程管理的功能后,可以同时开展文件系统部分功能的增强或实现虚拟内存两部分工作。在Nachos中,实现了两套文件系统,它们对外接口是完全一样的:一套称作为FILESYS_STUB,它是建立在UNIX文件系统之上的,而不使用Nachos的模拟磁盘,它主要用于读者先实现了用户程序和虚拟内存,然后再着手增强文件系统的功能;另一套是Nachos的文件系统,它是实现在Nachos的虚拟磁盘上的。当整个系统完成之后,只能使用第二套文件系统的实现。以下我们只分析在Nachos文件系统的实现:classFileSystem{public:FileSystem(boolformat);//生成方法boolCreate(char*name,intinitialSize);//生成一个文件OpenFile*Open(char*name);//打开一个文件boolRemove(char*name);//删除一个文件voidList();//列出文件系统中所有的文件//(实际上就是根目录中所有的文件)voidPrint();//列出文件系统中所有的文件和它
//thisstatemetistoformastringtobeusedasthenamefor
//produderi.
sprintf(prod_names[i],"producer_%d",i);
//Putthecodetocreateandforkanewproducerthreadusing
//thenameinprod_names[i]and
//integeriastheargumentoffunction"Producer"
producers[i]=newThread(prod_names[i]);//创建生产者线程
producers[i]->Fork(Producer,i);
};
//createandforkN_CONSofconsumerthreads
for(i=0;i{//thisstatemetistoformastringtobeusedasthenamefor//consumeri.sprintf(cons_names[i],"consumer_%d",i);//Putthecodetocreateandforkanewconsumerthreadusing//thenameincons_names[i]and//integeriastheargumentoffunction"Consumer"consumers[i]=newThread(cons_names[i]);//创建消费者线程consumers[i]->Fork(Consumer,i);};}P操作://////对信号量进行加锁voidSemaphore::P(){IntStatusoldLevel=interrupt->SetLevel(IntOff);//disableinterruptswhile(value==0){//semaphorenotavailablequeue->Append((void*)currentThread);//sogotosleepcurrentThread->Sleep();}Value--;//semaphoreavailable,//consumeitsvalue(void)interrupt->SetLevel(oldLevel);//re-enableinterrupts}V操作:////////对信号量进行解锁voidSemaphore::V(){Thread*thread;IntStatusoldLevel=interrupt->SetLevel(IntOff);thread=(Thread*)queue->Remove();if(thread!=NULL)//makethreadready,consumingtheVimmediatelyscheduler->ReadyToRun(thread);value++;(void)interrupt->SetLevel(oldLevel);} 实验五:ExtendableFiles实验目的:1,本实验室会议的目的是帮助你开始工作,扩大Nachos文件系统。 2,我们特别希望新的Nachos,文件系统具有以下功能:当一个文件被创建,它的初始大小可以设置为0。 3,文件的大小可以增加,如果更多的数据被写入文件。 实验分析以及主要代码:由于要对文件系统进行修改,首先需要明白其文件的存储结构。nachos和unix有较大的差别,通过查阅资料具体表现在一下方面:1.在磁盘的组织结构方面Nachos中文件同样有其inode和一般存储磁盘块,即Nachos物理磁盘的扇区。但是它不象UNIX一样,将文件系统中所有文件的inode存放在一起,即inode区中。每个Nachos文件的inode占用一个单独的扇区,分散在物理磁盘的任何地方,同一般存储扇区用同样的方式进行申请和回收。它没有文件系统管理块,是通过位图(Bitmap)来管理整个磁盘上的空闲块。2.在文件系统空闲磁盘数据块和inode块管理方面Nachos中有一个特殊的文件,即位图文件。该文件存放的是整个文件系统的扇区使用情况的位图。如果一个扇区为空闲,则它在位图文件相应的位为0,否则为1。Nachos中没有专门对inode扇区进行管理。当需要申请一个扇区时,根据位图文件寻找一个空闲的扇区,并将其相应的位置为1。当释放一个扇区时,将位图中相应的位置为0。位图文件是一个临界资源,应该互斥访问。现有的文件系统没有实现互斥访问,所以每次只允许一个线程访问文件系统。位图文件的inode占据0号扇区。3.在文件系统的目录管理方面一般的文件系统都采用树状目录结构,有的UNIX文件系统还有目录之间的勾连,形成图状文件系统结构。Nachos则比较简单,只有一级目录,也就是只有根目录,所有的文件都在根目录下。而且根目录中可以存放的文件数是有限的。Nachos文件系统的根目录同样也是通过文件方式存放的,它的inode占据了1号扇区。4.文件的索引结构上Nachos同一般的UNIX一样,采用索引表进行物理地址和逻辑地址之间的转换,索引表存放在文件的inode中。但是目前Nachos采用的索引都是直接索引,所以Nachos的最大文件长度不能大于4K。5.Nachos文件系统除了在以上几点上有所不足外,还有以下一些不完善的地方:●必须在文件生成时创建索引表。所以Nachos在创建一个文件时,必须给出文件的大小;而且当文件生成后,就不能改变文件的大小。●目前该文件系统没有Cache机制●目前文件系统的健壮性不够强。当正在使用文件系统时,如果突然系统中断,文件系统中的内容可能不保证正确。在Nachos文件系统中,许多数据结构既可存放在宿主机内存里,又可存放在磁盘上。为了一致起见,文件系统中Synchdisk以上的类都有一个FetchFrom成员方法,它把数据结构从磁盘读到内存;还有一个WriteBack成员方法,与FetchFrom相反,它把数据结构从内存写回磁盘。在内存中的数据结构与磁盘上的完全一致,这给管理带来了不少方便。1.同步磁盘分析(文件synchdisk.cc、synchdisk.h)和其它设备一样,Nachos模拟的磁盘是异步设备。当发出访问磁盘的请求后立刻返回,当从磁盘读出或写入数据结束后,发出磁盘中断,说明一次磁盘访问真正结束。Nachos是一个多线程的系统,如果多个线程同时对磁盘进行访问,会引起系统的混乱。所以必须作出这样的限制:●同时只能有一个线程访问磁盘●当发出磁盘访问请求后,必须等待访问的真正结束。这两个限制就是实现同步磁盘的目的。SynchDisk的类定义和实现如下所示:classSynchDisk{public:SynchDisk(char*name);//生成一个同步磁盘~SynchDisk();//析构方法voidReadSector(intsectorNumber,char*data);//同步读写磁盘,只有当真正读写完毕voidWriteSector(intsectorNumber,char*data);//后返回voidRequestDone();//磁盘中断处理时调用private:Disk*disk;//物理异步磁盘设备Semaphore*semaphore;//控制读写磁盘返回的信号量Lock*lock;//控制只有一个线程访问的锁};以ReadSector为例来说明同步磁盘的工作机制:voidSynchDisk::ReadSector(intsectorNumber,char*data){lock->Acquire();//加锁(一次只允许一个线程访问磁盘)disk->ReadRequest(sectorNumber,data);//对磁盘进行读访问请求semaphore->P();//等待磁盘中断的到来lock->Release();//解锁(访问结束)}当线程向磁盘设备发出读访问请求后,等待磁盘中断的到来。一旦磁盘中断来到,中断处理程序执行semaphore->V()操作,ReadSector得以继续运行。对磁盘同步写也基于同样的原理。2.位图模块分析(文件bitmap.cc、bitmap.h)在Nachos的文件系统中,是通过位图来管理空闲块的。Nachos的物理磁盘是以扇区为访问单位的,将扇区从0开始编号。所谓位图管理,就是将这些编号填入一张表,表中为0的地方说明该扇区没有被占用,而非0位置说明该扇区已被占用。这部分内容是用BitMap类实现的。BitMap类的实现比较简单,这里只是介绍其接口。classBitMap{public:BitMap(intnitems);//初始化方法,给出位图的大小,将所有位标明未用~BitMap();//析构方法voidMark(intwhich);//标志第which位被占用voidClear(intwhich);//清除第which位boolTest(intwhich);//测试第which位是否被占用,若是,返回TRUEintFind();//找到第一个未被占用的位,标志其被占用;//若没有找到,返回-1intNumClear();//返回多少位没有被占用voidPrint();//打印出整个位图(调试用)voidFetchFrom(OpenFile*file);//从一个文件中读出位图voidWriteBack(OpenFile*file);//将位图内容写入文件private:...//内部实现属性};3.文件系统模块分析(文件filesys.cc、filesys.h)读者在增强了线程管理的功能后,可以同时开展文件系统部分功能的增强或实现虚拟内存两部分工作。在Nachos中,实现了两套文件系统,它们对外接口是完全一样的:一套称作为FILESYS_STUB,它是建立在UNIX文件系统之上的,而不使用Nachos的模拟磁盘,它主要用于读者先实现了用户程序和虚拟内存,然后再着手增强文件系统的功能;另一套是Nachos的文件系统,它是实现在Nachos的虚拟磁盘上的。当整个系统完成之后,只能使用第二套文件系统的实现。以下我们只分析在Nachos文件系统的实现:classFileSystem{public:FileSystem(boolformat);//生成方法boolCreate(char*name,intinitialSize);//生成一个文件OpenFile*Open(char*name);//打开一个文件boolRemove(char*name);//删除一个文件voidList();//列出文件系统中所有的文件//(实际上就是根目录中所有的文件)voidPrint();//列出文件系统中所有的文件和它
//consumeri.
sprintf(cons_names[i],"consumer_%d",i);
//Putthecodetocreateandforkanewconsumerthreadusing
//thenameincons_names[i]and
//integeriastheargumentoffunction"Consumer"
consumers[i]=newThread(cons_names[i]);//创建消费者线程
consumers[i]->Fork(Consumer,i);
P操作:
//////对信号量进行加锁
voidSemaphore:
:
P()
IntStatusoldLevel=interrupt->SetLevel(IntOff);//disableinterrupts
while(value==0){//semaphorenotavailable
queue->Append((void*)currentThread);//sogotosleep
currentThread->Sleep();
Value--;//semaphoreavailable,
//consumeitsvalue
(void)interrupt->SetLevel(oldLevel);//re-enableinterrupts
V操作:
////////对信号量进行解锁
V()
Thread*thread;
IntStatusoldLevel=interrupt->SetLevel(IntOff);
thread=(Thread*)queue->Remove();
if(thread!
=NULL)
//makethreadready,consumingtheVimmediately
scheduler->ReadyToRun(thread);
value++;
(void)interrupt->SetLevel(oldLevel);
实验五:
ExtendableFiles
1,本实验室会议的目的是帮助你开始工作,扩大Nachos文件系统。
2,我们特别希望新的Nachos,文件系统具有以下功能:
当一个文件被创建,它的初始大小可以设置为0。
3,文件的大小可以增加,如果更多的数据被写入文件。
实验分析以及主要代码:
由于要对文件系统进行修改,首先需要明白其文件的存储结构。
nachos和unix有较大的差别,通过查阅资料具体表现在一下方面:
1.在磁盘的组织结构方面
Nachos中文件同样有其inode和一般存储磁盘块,即Nachos物理磁盘的扇区。
但是它不象UNIX一样,将文件系统中所有文件的inode存放在一起,即inode区中。
每个Nachos文件的inode占用一个单独的扇区,分散在物理磁盘的任何地方,同一般存储扇区用同样的方式进行申请和回收。
它没有文件系统管理块,是通过位图(Bitmap)来管理整个磁盘上的空闲块。
2.在文件系统空闲磁盘数据块和inode块管理方面
Nachos中有一个特殊的文件,即位图文件。
该文件存放的是整个文件系统的扇区使用情况的位图。
如果一个扇区为空闲,则它在位图文件相应的位为0,否则为1。
Nachos中没有专门对inode扇区进行管理。
当需要申请一个扇区时,根据位图文件寻找一个空闲的扇区,并将其相应的位置为1。
当释放一个扇区时,将位图中相应的位置为0。
位图文件是一个临界资源,应该互斥访问。
现有的文件系统没有实现互斥访问,所以每次只允许一个线程访问文件系统。
位图文件的inode占据0号扇区。
3.在文件系统的目录管理方面
一般的文件系统都采用树状目录结构,有的UNIX文件系统还有目录之间的勾连,形成图状文件系统结构。
Nachos则比较简单,只有一级目录,也就是只有根目录,所有的文件都在根目录下。
而且根目录中可以存放的文件数是有限的。
Nachos文件系统的根目录同样也是通过文件方式存放的,它的inode占据了1号扇区。
4.文件的索引结构上
Nachos同一般的UNIX一样,采用索引表进行物理地址和逻辑地址之间的转换,索引表存放在文件的inode中。
但是目前Nachos采用的索引都是直接索引,所以Nachos的最大文件长度不能大于4K。
5.Nachos文件系统除了在以上几点上有所不足外,还有以下一些不完善的地方:
●必须在文件生成时创建索引表。
所以Nachos在创建一个文件时,必须给出文件的大小;而且当文件生成后,就不能改变文件的大小。
●目前该文件系统没有Cache机制
●目前文件系统的健壮性不够强。
当正在使用文件系统时,如果突然系统中断,文件系统中的内容可能不保证正确。
在Nachos文件系统中,许多数据结构既可存放在宿主机内存里,又可存放在磁盘上。
为了一致起见,文件系统中Synchdisk以上的类都有一个FetchFrom成员方法,它把数据结构从磁盘读到内存;还有一个WriteBack成员方法,与FetchFrom相反,它把数据结构从内存写回磁盘。
在内存中的数据结构与磁盘上的完全一致,这给管理带来了不少方便。
1.同步磁盘分析(文件synchdisk.cc、synchdisk.h)
和其它设备一样,Nachos模拟的磁盘是异步设备。
当发出访问磁盘的请求后立刻返回,当从磁盘读出或写入数据结束后,发出磁盘中断,说明一次磁盘访问真正结束。
Nachos是一个多线程的系统,如果多个线程同时对磁盘进行访问,会引起系统的混乱。
所以必须作出这样的限制:
●同时只能有一个线程访问磁盘
●当发出磁盘访问请求后,必须等待访问的真正结束。
这两个限制就是实现同步磁盘的目的。
SynchDisk的类定义和实现如下所示:
classSynchDisk{
public:
SynchDisk(char*name);//生成一个同步磁盘
~SynchDisk();//析构方法
voidReadSector(intsectorNumber,char*data);//同步读写磁盘,只有当真正读写完毕
voidWriteSector(intsectorNumber,char*data);//后返回
voidRequestDone();//磁盘中断处理时调用
private:
Disk*disk;//物理异步磁盘设备
Semaphore*semaphore;//控制读写磁盘返回的信号量
Lock*lock;//控制只有一个线程访问的锁
以ReadSector为例来说明同步磁盘的工作机制:
voidSynchDisk:
ReadSector(intsectorNumber,char*data)
lock->Acquire();//加锁(一次只允许一个线程访问磁盘)
disk->ReadRequest(sectorNumber,data);//对磁盘进行读访问请求
semaphore->P();//等待磁盘中断的到来
lock->Release();//解锁(访问结束)
当线程向磁盘设备发出读访问请求后,等待磁盘中断的到来。
一旦磁盘中断来到,中断处理程序执行semaphore->V()操作,ReadSector得以继续运行。
对磁盘同步写也基于同样的原理。
2.位图模块分析(文件bitmap.cc、bitmap.h)
在Nachos的文件系统中,是通过位图来管理空闲块的。
Nachos的物理磁盘是以扇区为访问单位的,将扇区从0开始编号。
所谓位图管理,就是将这些编号填入一张表,表中为0的地方说明该扇区没有被占用,而非0位置说明该扇区已被占用。
这部分内容是用BitMap类实现的。
BitMap类的实现比较简单,这里只是介绍其接口。
classBitMap{
BitMap(intnitems);//初始化方法,给出位图的大小,将所有位标明未用
~BitMap();//析构方法
voidMark(intwhich);//标志第which位被占用
voidClear(intwhich);//清除第which位
boolTest(intwhich);//测试第which位是否被占用,若是,返回TRUE
intFind();//找到第一个未被占用的位,标志其被占用;
//若没有找到,返回-1
intNumClear();//返回多少位没有被占用
voidPrint();//打印出整个位图(调试用)
voidFetchFrom(OpenFile*file);//从一个文件中读出位图
voidWriteBack(OpenFile*file);//将位图内容写入文件
...//内部实现属性
3.文件系统模块分析(文件filesys.cc、filesys.h)
读者在增强了线程管理的功能后,可以同时开展文件系统部分功能的增强或实现虚拟内存两部分工作。
在Nachos中,实现了两套文件系统,它们对外接口是完全一样的:
一套称作为FILESYS_STUB,它是建立在UNIX文件系统之上的,而不使用Nachos的模拟磁盘,它主要用于读者先实现了用户程序和虚拟内存,然后再着手增强文件系统的功能;另一套是Nachos的文件系统,它是实现在Nachos的虚拟磁盘上的。
当整个系统完成之后,只能使用第二套文件系统的实现。
以下我们只分析在Nachos文件系统的实现:
classFileSystem{
FileSystem(boolformat);//生成方法
boolCreate(char*name,intinitialSize);//生成一个文件
OpenFile*Open(char*name);//打开一个文件
boolRemove(char*name);//删除一个文件
voidList();//列出文件系统中所有的文件
//(实际上就是根目录中所有的文件)
voidPrint();//列出文件系统中所有的文件和它
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1