读者写者问题实验报告.docx
《读者写者问题实验报告.docx》由会员分享,可在线阅读,更多相关《读者写者问题实验报告.docx(9页珍藏版)》请在冰豆网上搜索。
读者写者问题实验报告
读者写者问题实验报告
北京电子科技学院(BESTI)
实验报告课程:
操作系统班级:
姓名:
学号:
0921成绩:
指导教师:
实验日期:
2011.11.22徐小青
实验密级:
预习程度:
实验时间:
/12:
50-15:
20代码
仪器组次:
必修/选修:
实验序号:
A04必修
(一)实验名称:
用信号量来实现读者-写者问题
实验目的与要求:
理解进程(或线程)及信号量的概念
实验仪器:
名称型号数量
DELLPP33L微机1
一、实验目的:
理解进程(或线程)及信号量的概念
二、实验内容:
1、定义一个数据缓存buffer及用于实现同步互斥的信号量。
2、定义一个读者函数:
当有写者在占用buffer时,读者应该等待,直到写者不再使用该
buffer。
当有其他读者在占用buffer时,读者可对buffer进行读取操作。
当buffer中有数据时,则从其中读取一个数据,并显示然后退出。
当buffer中没有数据时,应等待,直到buffer中有数据可读。
3、定义一个写者函数
当有读者在占用buffer时,写者应该等待,直到所有的读者都退出
为止。
当有其他写者占用buffer时,该写者应该等待,直到占用buffer的写
者退出为止。
当buffer有空闲时,写者应该在buffer中写入一个数据并退出。
当buffer满时,写者应该等待,直到buffer有空闲为止。
、定义主函数,在其中可以任意创建读者与写者。
4
可根据用户输入创建读者或写者进程(线程)。
三、实验当堂完成内容:
1,将设计好的思路以代码形式呈现,并调通。
2,将数据改变,看结果是否符合预期设想
3,与同学交流,将代码完善。
四、设计思想:
读进程:
read()
{
P(Sr);申请区域
P(Scot);锁定读者计数器
first=first+1;
if(first==1)
P(Sdoc);
V(Scnt);解锁读者计数器
开始读;
P(Scnt);锁定读者计数器
V(Sdoc);
V(Scnt);
V(Sr);
}
写进程:
write()
{
P(sdoc);
开始写;
V(sdoc);
}
主函数设计思想:
开始
创建Sdoc、Sr、Scnt三个信
号量
inti=0
否i是
创建读者线程
i++
iintj=0
否i是
创建写者线程依次等待与执行j++i结束
i
五、代码及具体解释:
#include
#include
#include
#defineP(S)WaitForSingleObject(S,INFINITE)//这是Windows下多线程工作的P操作
#defineV(S)ReleaseSemaphore(S,1,NULL)//这是Windows下多线程工作的V操作
constintRN=5;//所有读者总数(可以改变)
constintWN=3;//所有写者总数(可以改变)
HANDLESdoc;//文档信号量——互斥量(临界区的信号量题目要求是1)HANDLESr;//读者信号量——广义信号量(一次最多有多少个读者在读)HANDLEScnt;//保护g_cntReader的互斥量(目前有多少读者正在读)intg_cntReader=0;//读者个数计数器
//funcname:
JustWait()//note:
显示一些信息,让后等待
//retval:
void
//
//+Parameter:
//[int]-nReader读者(写者)编号,读者>0,写者<0
//[int]-min操作等待的最短时间
//[int]-max操作等待得最长时间,实际等待的时间介于两者之间//[LPCSTR]-info要显示的信息
voidJustWait(intnReader,intmin,intmax,LPCSTRinfo);
DWORDWINAPIReader(LPVOIDlpPara);
DWORDWINAPIWriter(LPVOIDlpPara);//这是主函数
voidmain()
{
Sdoc=CreateSemaphore(NULL,1,1,"Document");//创建信号量初值,最大信号量值
Sr=CreateSemaphore(NULL,3,3,"ReaderNumber");//一次最多允许3个
读者读
Scnt=CreateSemaphore(NULL,1,1,"ReaderCounterProtect");//他也是一个互斥信号量,初值为1
HANDLEthreads[RN+WN];
for(inti=0;ithreads[i]=CreateThread(0,0,Reader,0,0,0);
for(intj=0;jthreads[j+RN]=CreateThread(0,0,Writer,0,0,0);
WaitForMultipleObjects(RN+WN,threads,TRUE,INFINITE);
}
//读者线程
DWORDWINAPIReader(LPVOIDlpPara)
{
//注意是静态变量,可以使每来一个读者增加一
staticintreader_num=1;
inti=reader_num++;
intx=0;
while(x<=5)
{
JustWait(i,1,2,"我想读");//1s的时候来,给2s的时间去读
P(Sr);//读者未满
P(Scnt);//锁定读者计数器
printf("还有%d个读者在读,读者%d进入\n",g_cntReader,i);
g_cntReader++;
if(g_cntReader==1)//如果是第一个读者
{
JustWait(i,1,2,"我是第一个!
");
P(Sdoc);//锁定文档
printf("读者%d说:
有人在读,不可写文件\n",i);
JustWait(i,1,2,"我可以读文件了~");
}
V(Scnt);//解锁读者计数器释放
JustWait(i,2,5,"我在读");//读ing…………
JustWait(i,1,2,"我将要离开~");
P(Scnt);//锁定读者计数器
g_cntReader--;
if(g_cntReader==0)//如果是最后一个
{
JustWait(i,1,2,"我是最后一个!
");
printf("读者%d说:
可以对文件操作了~~~~\n",i);
V(Sdoc);//解锁文档
}
printf("还有%d个读者在,读者%d离开\n",g_cntReader,i);
V(Scnt);//解锁读者计数器
V(Sr);//离开
JustWait(i,5,3,"结束");
x++;
printf("%d\n",x);
}
return0;
}
DWORDWINAPIWriter(LPVOIDlpPara)
{
//注意是静态变量,可以使每来一个写者减去一,注意初值是负值
staticintg_cnt=-1;
intj=g_cnt--;
while
(1)
{
JustWait(j,2,4,"我想写");
//锁定文档
P(Sdoc);
printf("\t写者%d说:
文件正在修改不可操作\n",-j);
JustWait(j,4,3,"写?
?
?
");//写ing……
JustWait(j,1,2,"写完了,离开");
printf("写者%d说:
可以对文件操作了\n",-j);
V(Sdoc);//解锁文档
JustWait(j,8,4,"休息了");
}
return0;
}
voidJustWait(intnReader,intmin,intmax,LPCSTRinfo)//min为读者到来时间,max为读者离开时间
{
constintBASETIME=1000;//等待时间的基本量,以毫秒表示
intwait_time=0;//实际等待得时间
if(max==min)//判断是为了避免%0错误,注意取随机值
wait_time=min*BASETIME;//处理时间为0;
else
chars_out[128];//最终显示的信息缓冲
if(nReader>0)//读者大于0,写者小于0
sprintf(s_out,"读者%d说:
%s\n",nReader,info);
else
sprintf(s_out,"\t写者%d说:
%s\n",-nReader,info);
printf(s_out);//打印
Sleep(wait_time);//然后等待
}
//其设计思想是:
读者在读,来了写着,创建写着线程,利用时间片区分他们。
即定好某一个时间写者来,读一定时间以后离开。
六、实验编译过程遇到的问题:
1,未确定应该使用多线程还是单线程。
解决:
多线程是即使有读者在里边读,外边的写者依旧可以创建自己的线程,知道让出区域,便可以进去。
基于Windows里面具有API函数库,便确定使用多线程来处理。
2,在区域内的读者究竟多少个,
解决:
在读者写者问题中,区域内到底有多少个读者允许同时读。
故本次实验设信号量,Sr来计数本次实验中的临界区内的读者数量。
而且设定上限是3.
3,进程调度的机制是什么,
解决:
时间片轮流并设定。
每个读者或者写者定一个时间来,再定一定长度的时间离开。
比如JustWait(i,1,2,"我想读")是说1s的时候来,停留2s后出去。
七、实验运行中遇到的问题:
1、读者写者的个数不好计数,出现错误。
解决:
nReader的正数值表示读者数量,负值表示写着数量。
读者数量++,写着数量--,用一个变量计数并解决问题。
2、读者来的顺序不一定,是因为操作系统具有随机性。
解决:
等待时间具有随机性。
wait_time=rand()%(max*BASETIME-min*BASETIME)+min*BASETIME;
八、实验体会与心得:
此次实验是操作系统课程的第一次实验,编的是经典的读者写者问题。
首先要对读者写者问题有一个深刻的认识,才能落实到代码量上。
此次实验很多同学使用Linux下或者Unix的环境下编程,让我大开眼界。
我选择了比较大众化的C语言编程来实现此次实验。
在开始的时候对如何将读者写者问题转化到代码量非常疑惑,因为没有编写操作系统实验的思想,后来去图书馆查阅了一些书籍,看了一些伪代码,才有了一个初步的认识,最终确定用多线程编写。
大局方面,计算机的时钟是以毫秒来计算,因此BaseTime=1000,即以1s为一个时钟间隔。
在信号量的设计上,我采取了三个信号量,Sdoc(文档信号量,也是互斥量,此文档临界区的信号量,按照题目要求是1),Sr(读者信号量,一次临界区里最多有多少读者在里边读),Scnt(保护g_cntReader的互斥量)。
最后完善细节将代码调通。
这个过程很艰苦,而且有时候想不清楚的时候还要问其他同学,非常不容易。
但是这种学习使我收获很大。
学习不能闭门造车,也不能完全借鉴,要自己思考不清后交流。
期待下一次的操作系统实验,希望可有更多的收获