操作系统OS报告读者与写者问题进程同步问题Word文件下载.docx
- 文档编号:22088945
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:20
- 大小:130.05KB
操作系统OS报告读者与写者问题进程同步问题Word文件下载.docx
《操作系统OS报告读者与写者问题进程同步问题Word文件下载.docx》由会员分享,可在线阅读,更多相关《操作系统OS报告读者与写者问题进程同步问题Word文件下载.docx(20页珍藏版)》请在冰豆网上搜索。
3Sleep可在指定的时间内挂起当前线程。
VOIDSleep(
DWORDdwMilliseconds//sleeptime
4信号量控制:
WaitForSingleObject可在指定的时间内等待指定对象为可用状态;
DWORDWaitForSingleObject(
HANDLEhHandle,//handletoobject
DWORDdwMilliseconds//time-outinterval
hHandle为等待的对象,也就是实现同步或者互斥的对象。
该函数一执行,相应的信号量就减去1,如果信号量小于等于0,那么他一直在循环。
5实现信号量互斥和同步
CreateSemaphore用于创建信号量,根据参数的不同可以利用它实现互斥和同步。
ReleaseSemaphore用于释放信号量,使用后相应的信号量加1
HANDLECreateSemaphore(
LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,//SD
LONG,lInitialCount,//initialcount
LONG,lMaximumCount,//maximumcount
LPCTSTRlpName//objectname
);
ReleaseSemaphore(
HANDLEhSemaphore,//handletosemaphore
LONGlRelseaseCount,//contincrementamount
LPLONGlpPreviousCount//previouscount
三、题目分析
将所有的读者和所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。
(1)构筑读者进程和写者进程间的临界区
题目中说的一批数据被多个读者、写者共享使用,允许多个读者同时访问这些数据,但是如果有一个写者在访问数据时,就不允许其他读者或写者使用,所以,对这一批数据既要保证读者和写者互斥使用,也要保证写者与写者互斥使用。
也就是说,在读者进程程序中,使用数据的程序段应该构成临界区;
在写者进程程序中,使用数据的程序段应该构成临界区。
(2)判定是否是第一个读者
根据上面的分析,希望在读者进程中有一个办法能判定请求进入临界区的是否是第一个读者。
如果是第一个读者,就对信号量wsem做P操作,以取得和写者的同步。
为此,设置一个变量rfirst,初值为0.任何一个读者运行时,都现在rfirst上加1,然后判定他是否取值为1.如果是1,则做P(wrt),否则不做。
(3)判定是否是第一个写者
原理同
(2)判定是否为第一个读者。
(4)写者优先问题的解决需要用到的如下的信号量和变量
rsem:
初值为1的互斥信号量,在至少有一个写者准备访问数据时就不允许随后来的读者访问数据
wserm:
初值为1的互斥信号量,之后有一个写者访问数据时其他写者和读者就被阻止对数据的访问
ReadMutex:
创建写者的互斥信号量,初值为1
WriteMutex:
创建读者的互斥信号量,初值为1
z:
初值为1的互斥信号量,在至少有一个写着准备访问数据、且后面已经来一个读者时再来的读者将在这个信号量上等待
rifrrst:
读者计数变量,初值为0
wfirst:
写者计数变量,初值为0
写者优先的PV原语:
reader(i):
{
P(z);
P(rsem);
P(ReadMutex);
rfirst=rfirst+1;
if(rfirst==1)
P(wsem);
V(ReadMutex);
V(rsem);
V(z);
读取所需数据;
rfirst=rfirst-1;
if(rfirst==0)
V(wsem);
}
Writer():
P(WriteMutex);
wfirst=wfirst+1;
if(wfirst==1)
V(WritedMutex);
改写所需数据;
wfirst=wfirst-1;
if(wfirst==0)
V(WriteMutex);
读者写者
图3.1读者-写者的完整流程框图
(5)读者优先
与写者优先算法相反,有一个读者优先的算法,即只要有读者在读数据,写者被拒绝在临界区外面,如果有源源不断的写者来,但是只要写者不是第一个,那么写者将会永远被拒绝在临界区外面。
wrt:
:
初值为1的互斥信号量,只要有一个写者访问数据,则其他写者和读者就要被阻止对数据的访问。
mutex:
保证读者互斥操作first的信号量,初值为1
first:
读者优先的PV原语:
write():
P(wrt);
对数据进行修改;
V(wrt);
read():
P(mutex);
first=first+1;
if(first==1)
P(wrt);
V(mutex);
读取所需数据
if(first==0)
V(wrt);
四、概要设计
(1)控制流程
用CheckPersonList(PersonLists)函数检查PersonLists中是否有为创建的进程(读写者)。
如果有则创建相应的读写线程
(2)创建读写者
用boolCreateReader(intStartTime,intWorkTime)函数创建读者写者相应的线程,其中由windows提供的函数为CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&
dwThreadID);
返回的是DWORD型变量。
在CreateReader(intStartTime,intWorkTime)中还会初始化相应的读写者的基本信息,例如何时申请数据何时读数据何时关闭线程等等。
(3)读写者进程
参见图2.1读者-写者的完整流程图。
(4)同步与互斥
WaitForSingleObject(信号量名字,infinite)和ReleaseSemaphore(信号量名字,1,null)用于实现同步于互斥,执行WaitForSingleObject(信号量名字,infinite)信号量相应的信号量减1,执行ReleaseSemaphore(信号量名字,1,null)恢复1。
五、代码及流程
//写者优先算法
#include<
windows.h>
ctype.h>
stdio.h>
string.h>
stdlib.h>
malloc.h>
#defineMAX_PERSON10
#defineREADER0
#defineWRITER1
#defineEND-1
#defineRREADER
#defineWWRITER
typedefstruct_Person
HANDLEThread;
intType;
intStartTime;
intWorkTime;
intID;
}Person;
PersonPersons[MAX_PERSON];
intNumPerson=0;
longCurrentTime=0;
intPersonLists[]={
1,R,1,3,
2,W,2,5,/*读写互斥*/
3,W,5,5,/*写写互斥*/
4,R,3,5,/*写读互斥*/
5,R,15,2,/*读读不互斥*/
END,
};
intrfirst=0;
intwfirst=0;
intNumOfReaders=0;
intNumOfWriters=0;
HANDLErsem;
/*初值为1的互斥信号量,在至少有一个写者准备访问数据时就不允许随后来的读者访问数据*/
HANDLEwsem;
/*初值为1的互斥信号量,之后有一个写者访问数据时其他写者和读者就被阻止对数据的访问*/
HANDLEz;
/*初值为1的互斥信号量,在至少有一个写着准备访问数据、且后面已经来一个读者时再来的读者将在这个信号量上等待*/
HANDLEReadMutex;
/*创建写者的互斥信号量,初值为1*/
HANDLEWriteMutex;
/*创建读者的互斥信号量,初值为1*/
voidCheckPersonList(int*pPersonList);
/*查看人数,为创建读写者线程*/
boolCreateReader(intStartTime,intWorkTime);
boolCreateWriter(intStartTime,intWorkTime);
DWORDWINAPIReaderProc(LPVOIDlpParam);
/*读者进程程序*/
DWORDWINAPIWriterProc(LPVOIDlpParam);
/*写着进程程序*/
#include"
Writerprior.h"
intmain()
{
rsem=CreateSemaphore(NULL,1,1,NULL);
wsem=CreateSemaphore(NULL,1,1,NULL);
z=CreateSemaphore(NULL,1,1,NULL);
ReadMutex=CreateSemaphore(NULL,1,1,NULL);
WriteMutex=CreateSemaphore(NULL,1,1,NULL);
CurrentTime=0;
while(true)//模拟20个时钟周期
{
CheckPersonList(PersonLists);
CurrentTime++;
Sleep(600);
printf("
当前时间=%d:
\n"
CurrentTime);
if(CurrentTime==20)
break;
}
system("
pause"
CloseHandle(rsem);
CloseHandle(wsem);
CloseHandle(z);
CloseHandle(ReadMutex);
CloseHandle(WriteMutex);
return0;
voidCheckPersonList(int*pPersonLists)
inti=0;
int*pList=pPersonLists;
boolP;
while(pList[0]!
=END)
if(pList[2]==CurrentTime)
{
switch(pList[1])
{
caseR:
P=CreateReader(pList[2],pList[3]);
//创建一个读者
break;
caseW:
P=CreateWriter(pList[2],pList[3]);
//创建一个写者
}
if(!
P)
printf("
CreatePerson%diswrong\n"
pList[0]);
}
pList+=4;
//数组的指针指向第二个人
DWORDWINAPIReaderProc(LPVOIDlpParam)
Person*pPerson=(Person*)lpParam;
pPerson->
ID=++NumOfReaders;
WaitForSingleObject(z,INFINITE);
//P(z),其余读者在此排队
printf("
\t\t读者%d申请读数据...\n"
pPerson->
ID);
WaitForSingleObject(rsem,INFINITE);
//P(rsem),一个读者与一个写着再次竞争数据的使用权
//printf("
Reader%disrequestingtheSharedBuffer...\n"
WaitForSingleObject(ReadMutex,INFINITE);
//P(ReadMutex),读者请求进入rfirst临界区
rfirst++;
if(rfirst==1)//是否是第一个读者
WaitForSingleObject(wsem,INFINITE);
//读者在此处与写者进行同步
ReleaseSemaphore(ReadMutex,1,NULL);
//退出rfirst临界区,V(ReadMutex)
ReleaseSemaphore(rsem,1,NULL);
ReleaseSemaphore(z,1,NULL);
//V(z)
//读取所需数据,将现在时间赋值给读者,用以计算结束时间
\t\t读者%d申请成功\n"
StartTime=CurrentTime;
\t\t读者%d正在读数据...\n"
while(CurrentTime<
StartTime+pPerson->
WorkTime)
//模拟读数据
\t\t读者%d读完数据退出\n"
rfirst--;
if(rfirst==0)//是最后一个读者?
ReleaseSemaphore(wsem,1,NULL);
//没有读者了,写者放行
//退出读者临界区
ExitThread(0);
//关闭读者线程
DWORDWINAPIWriterProc(LPVOIDlpParam)//写者进程程序
ID=++NumOfWriters;
\t\t写者%d正在申请写数据...\n"
WaitForSingleObject(WriteMutex,INFINITE);
//请求进入写者临界区
wfirst=wfirst++;
if(wfirst==1)
WaitForSingleObject(rsem,INFINITE);
//一个写者在此与读者取得同步
ReleaseSemaphore(WriteMutex,1,NULL);
//退出rfirst临界区
//其他写者在此等候进入写临界区
\t\t写者%d正在写数据...\n"
//模拟写数据
\t\t写者%d写完数据退出\n"
//退出进入写临界区
//请求进入wfirst临界区
wfirst=wfirst--;
if(wfirst==0)//是最后一个写者?
ReleaseSemaphore(rsem,1,NULL);
//没有写者了,向读者放行
//退出wfirst临界区
//关闭写者线程
boolCreateReader(intStartTime,intWorkTime)
DWORDdwThreadID;
Person*pPerson=&
Persons[NumPerson];
StartTime=StartTime;
WorkTime=WorkTime;
Type=READER;
NumPerson++;
//创建一个读者的新线程
Thread=CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&
if(pPerson->
Thread==NULL)
returnfalse;
returntrue;
boolCreateWriter(intStartTime,intWorkTime)
if(NumPerson>
=MAX_PERSON)
Person*pPerson=&
StartTime=StartTime;
WorkTime=WorkTime;
Type=WRITER;
//创建一个写者的新线程
Thread=CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&
六、运行结果
图6.1运行结果
结果分析:
顺序
开始时间(s)
执行时间(s)
Reader
1
3
2
5
15
Writer
表6.1
如上表,第一个读者1到达时间是第1s,执行时间是3s,即在第4s的时候结束,而在第2s的时候就写者1到达。
这时候,写者1被阻挡在z的临界区外面。
在第3s的时候,读者2到达,由于写者1在前面,所以同样被阻挡在z外面,在第4s读者1运行结束,写者1开始写数据,这是读者2被阻挡在rsem的临界区外面,在第5s的时候到达第二个写者,由于写写互斥,所以被阻挡在写者wsem的临界区外面。
第14s写者2退出,读者2才开始读数据。
读者3在第15s的时候到达,由于读读不存在互斥,所以两个读线程同时进行,知道第19s时读者2结束,整个模拟结束。
(过程请参考图6.2)
图6.2程序过程图
七、设计心得
通过这次操作系统的课程设计,我研究了读者与写者问题,进一步深入了解了同步与互斥机制。
比如什么是同步,什么是互斥,什么是信号量等等。
课程设计和平时的实验课比较起来有很大的差距,实验课只是将这一章的一部分内容练习操作一遍,而课程设计需要的是他们综合起来的东西,这要更难一些。
总体来说我认为操作系统这门学科在计算机科学当是中非常重要的。
他将我们学过的编程语言联系起来,可以说是第一次利用C语言利用windows的API与系统进行“沟通”。
总而言之,这次操作系统的课程设计收获颇丰,复习了许多东西,也从新学会了许多东西。
我想这也许就是课程设计的最终目的吧。
八、参考文献
[1]刘振安、刘燕君著.《C++程序设计课程设计》.北京:
机械工业出版社,2004
[2][美]AbrahamSilberschatz,PeterBaerGalvin,GregGagne著.郑扣根译.操作系统概念(第六版).北京:
高等教育出版社,2004
[3]陈向群,向勇等.Windows操作系统原理(第二版).北京:
机械工业出版社,2004.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 OS 报告 读者 问题 进程 同步