操作系统实验Synchronization Using Semaphores.docx

上传人:b****6 文档编号:3475604 上传时间:2022-11-23 格式:DOCX 页数:47 大小:34.39KB
下载 相关 举报
操作系统实验Synchronization Using Semaphores.docx_第1页
第1页 / 共47页
操作系统实验Synchronization Using Semaphores.docx_第2页
第2页 / 共47页
操作系统实验Synchronization Using Semaphores.docx_第3页
第3页 / 共47页
操作系统实验Synchronization Using Semaphores.docx_第4页
第4页 / 共47页
操作系统实验Synchronization Using Semaphores.docx_第5页
第5页 / 共47页
点击查看更多>>
下载资源
资源描述

操作系统实验Synchronization Using Semaphores.docx

《操作系统实验Synchronization Using Semaphores.docx》由会员分享,可在线阅读,更多相关《操作系统实验Synchronization Using Semaphores.docx(47页珍藏版)》请在冰豆网上搜索。

操作系统实验Synchronization Using Semaphores.docx

操作系统实验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();//列出文件系统中所有的文件和它

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 小升初

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1