操作系统实验Synchronization Using Semaphores.docx
- 文档编号:3475604
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:47
- 大小:34.39KB
操作系统实验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
#include
#include
#include
#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. // //---------------------------------------------------------------------- void Consumer(_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中是否有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"); Exit (1); } } } //---------------------------------------------------------------------- //ProdCons //Setupsemaphoresforsharedroundbufferand //createandforkproducersandconsumerthreads //---------------------------------------------------------------------- void 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_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);//disableinterrupts while(value==0){//semaphorenotavailable queue->Append((void*)currentThread);//sogotosleep currentThread->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,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{ public: BitMap(intnitems);//初始化方法,给出位图的大小,将所有位标明未用 ~BitMap();//析构方法 voidMark(intwhich);//标志第which位被占用 voidClear(intwhich);//清除第which位 boolTest(intwhich);//测试第which位是否被占用,若是,返回TRUE intFind();//找到第一个未被占用的位,标志其被占用; //若没有找到,返回-1 intNumClear();//返回多少位没有被占用 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();//列出文件系统中所有的文件和它
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统实验Synchronization Using Semaphores 操作系统 实验 Synchronization
![提示](https://static.bdocx.com/images/bang_tan.gif)