读者写者问题-操作系统实验报告文档格式.doc
- 文档编号:637465
- 上传时间:2023-04-29
- 格式:DOC
- 页数:14
- 大小:92.01KB
读者写者问题-操作系统实验报告文档格式.doc
《读者写者问题-操作系统实验报告文档格式.doc》由会员分享,可在线阅读,更多相关《读者写者问题-操作系统实验报告文档格式.doc(14页珍藏版)》请在冰点文库上搜索。
stdio.h>
stdlib.h>
intrcount=0;
//正在读的读者数量
intwcount=0;
//写者队列中等待写操作的写者数量
intread_id=0;
//读进程号
intwrite_id=0;
//写进程号
intw=1;
//读写互斥信号量
chartemp[300]={'
\0'
};
intchoice;
//用户选择读者优先OR写者优先
intsign;
//标识temp空的信号量0表示temp空
voidWFwakeup();
voidRFwakeup();
structrqueue{//读者等待队列
intreaders[200];
intindex;
}rq;
structwqueue{//写者等待队列
intwriters[200];
}wq;
/*voidfirst(){//初始化
inti;
rq.index=0;
wq.index=0;
for(i=0;
i<
20;
i++){
rq.readers[i]=0;
wq.writers[i]=0;
}
}*/
//*******************************************读进程读操作
voidread(){
inti=0;
read_id++;
if(rcount==0){//当前没有读进程在读可能有写进程在写可能CPU空闲
if(w==1){//如果CPU空闲,读者拿到CPU
w--;
//相当于一个P操作
rcount++;
if(temp[0]=='
){
sign=0;
if(choice==1){
rq.readers[rq.index++]=read_id;
//将读者进程加入等待队列
RFwakeup();
return;
}
else{
WFwakeup();
}//if
printf("
读者%d正在读\n"
read_id);
for(i=0;
i<
300;
i++){//读取temp内容即写者写的内容
if(temp[i]=='
printf("
\n"
);
}//if
printf("
%c"
temp[i]);
}//for
}//if
else{//写者线程正在执行
!
有写者在写不能读!
rq.readers[rq.index++]=read_id;
}//else
}//if
else{//rcount!
=1则知道当前已经有读者在读,读读不互斥,则这个读者可以直接进来了读
printf("
for(i=0;
i++){
if(temp[i]=='
return;
}
}//for
}//else
}
//***************************写进程写操作
voidwrite(){
write_id++;
if(w==0){
if(rcount!
=0){//有读者进程在执行
有读者在读不能写!
wq.writers[wq.index++]=write_id;
//将写者进程加入等待队列
wcount++;
return;
}
if(rcount==0){//rcount==0则当前无读者,但w=0,所以有写者在写
有写者在写不能写!
if(w==1){
w--;
写者%d正在写\n请输入要写的内容"
write_id);
scanf("
%s"
temp);
//while
//************************读者优先时唤醒进程
voidRFwakeup(){
intj=0;
intm,n;
m=rq.index;
// n=wq.index;
if(rcount==0){//当前无读进程,是写者在写--》停止运行写进程
boolreader_wait=false;
w=1;
写者已经写完\n"
sign=1;
//temp中已经有内容要置1
for(i=0;
=m;
i++){// index为当前读者队列中的等待进程数
if(rq.readers[i]!
=0){
reader_wait=true;
//确实有读者在等待
等待的读者%d正在读\n"
rq.readers[i]);
w=0;
for(j=0;
j<
j++){
if(temp[j]=='
printf("
break;
}//if
temp[j]);
}//for
rq.readers[i]=0;
rcount++;
rq.index--;
if(!
reader_wait){//没有读者等待,看是否有写者等待
for(inti=0;
=wq.index;
i++){//检查写者等待队列
if(wq.writers[i]!
w=0;
等待的写者%d正在写\n请输入要写入的内容"
wq.writers[i]);
scanf("
wq.writers[i]=0;
wcount--;
break;
// return;
=0读者正在读,stop读 此时若有等待必为写者
rcount=0;
w=1;
if(sign==0){
缓冲区空等待写者\n"
else{
读者已经读完\n"
i++){// 检查写者等待队列
=0){
}//else
//******************************************写者优先唤醒
voidWFwakeup(){
//n=wq.index;
boolwriter_wait=false;
i++){// index为当前写者队列中的等待进程数
if(wq.writers[i]!
writer_wait=true;
//确实有写者在等待
等待的写者%d正在写\n请输入要写的内容\n"
scanf("
wq.writers[i]=0;
wcount--;
break;
writer_wait){//没有xie者等待,看是否有du者等待
if(rq.readers[i]!
for(j=0;
if(temp[j]=='
printf("
rq.index--;
break;
}//if
}//for
rq.readers[i]=0;
rcount++;
// return;
for(inti=0;
}//for
voidmenu1(){
chari;
printf("
1-创建读者进程\n2-创建写者进程\n3-结束当前执行的进程\n4-退出程序\n"
*******************************************\n"
do{
当前队列中有读者:
%d个写者:
%d个\n"
rq.index,wcount);
----->
"
scanf("
&
i);
switch(i){
case'
1'
:
read();
break;
2'
write();
3'
RFwakeup();
4'
exit(0);
default:
输入错误请重新输入\n"
}while(true);
voidmenu2(){
WFwakeup();
voidmain(){
**************************************************************************\n"
20092104实验一\n1.读者优先\n2.写者优先\n"
scanf("
%d"
choice);
while
(1){
if(choice==1)
menu1();
if(choice==2)
menu2();
if(choice!
=1&
&
choice!
=2){
scanf("
实验流程图:
退出
写者优先
读者优先
写者优先唤醒
读者优先唤醒
写操作
读操作
是否有读者在读
有写者读者入队
N
Y
CPU是否空闲
有读者写者入队
Cpu是否空闲
进行读操作
进行写操作
缓冲区是否为空
有写者,写操作入队
入读者等待队列
调用读者优先唤醒
当前有无读者在读
有无读者等待
读者出队进行读操作直到读者队空
有无写者等待
返回
有读者说明若有等待必为写者
写者出队进行写操作直到写者队空
进行读操作直到读者队列为空
写者队列是否为空
进行写操作直到写者队列为空
核心部分设计思路:
分别用两个队列来存放等待的读者进程和写者进程,一个进程结束后就要将因他阻塞的进程唤醒,如果是读者优先,则先检查读者进程,如果发现读者进程不为空,就进行读操作,直到读者进程为空,才进行写操作;
同理,如果是写者优先,则先检查写进程,如果发现写者进程不为空,就进行写操作,直到写者进程为空,才进行读操作。
读写互斥:
只有当互斥信号量w=1并且当前读者数为0时,才可以进行写操作,对于读进程,w=1且当前读者数为0时,第一个读进程进行读操作,当当前读者数大于0时,不用判断互斥信号量w而直接进行读操作。
对缓冲区为空的情况,如果缓冲区为空时进行读操作,则会设置一个信号量标志缓冲区为空sign=0,不可以进行读操作,释放出CPU,调用唤醒函数唤醒写进程,此时会将此进程放入读者进程等待队列中等待写者来写数据再进行读操作,写者写完数据,缓冲区不空时,将标志置为缓冲区不空sign=1。
编译过程中遇到的问题:
1.编译过程中出现的一个很大的错误就是在构造队列的时候给变量index赋值了,系统提示错误
解决:
取消赋值,编写了一个初始化函数进行初始化,后来发现不初始化也没用什么问题,就注释掉了。
2.刚开始还会出现一些括号不匹配的错误,在后来的程序完善过程中,尽量给后括号做一个注释进行标识。
运行过程中遇到的问题:
1.不能接受非法字符,如果输入非法字符就会进入死循环,但是在switch外明明有检查语句。
通过单步跟踪,发现检查语句并没有起到作用,于是调整了一下结构,将检查语句放到switch里,既起到了检查的作用,同时也减少了代码量。
2.在读者进行读取数据时,总是会在读取完写者写的内容的后面出现一个小a。
也是通过单步跟踪,发现是判空和输出的顺序问题,如果先输出后判空的话,会多进行一次循环,导致输出一个小a,但是现在还是不太明白为什么多输出的是小a。
3.当缓冲区为空的时候创建了n-1个读进程,他们都在等待写进程写数据,然而等写进程写完数据后,这些读进程并没有进行读取,继续创建读进程,就会发现是读进程n在进行读取。
刚开始是以为参数设置问题,后来仔细一想,发现是没有在调用唤醒函数前没有将读进程放入读者等待队列中,于是在调用唤醒函数前,添加将读者进程放入等待队列的语句。
4.还出现了不少小错误,例如将i,j写错导致读者每次都会读300次用一个字母,没有设置信号量sign导致在缓冲区为空的时候还没有进行读操作就会有“读者已经读完”的错误提示等等。
也有一些原则性错误比如在唤醒函数中,读或者写进程结束后,将信号量置1,但是在队列中选择进程进行操作的时候,没有把信号量置0,导致了执行唤醒函数后进程不互斥的问题。
开始的程序中还设置了一些意义不大的变量,比较混乱,后来通过画简单的流程图,将意义不大的变量取消,理清了思路,解决了问题。
运行过程中的问题出现的问题比较多,但都不是特别大的问题,通过调试分析都得到了解决。
实验收获与心得:
这次实验耗时比较多,预习的时候并没有准备特别充分,程序还有很多问题,功能也不没有达到老师的要求。
实验过程中,一步一步由简到繁,完善程序的同时,问题也出现了不少,通过画简单的流程图,通过单步跟踪,通过分析理解,都得到了解决。
程序的缺点就是设置的变量过多,后来经过分析和调试,发现很多都是没有必要的,还让程序更加混乱,条理不清楚,后来去掉了不少。
这次实验让我更加深刻的理解了进程的信号量的概念和应用,在不断出现错误,发现错误,改正错误的过程中,对互斥信号量有了非常深刻的理解。
虽然程序的功能还不是很完善,但是自己调试成功的程序就非常有成就感。
下次实验我会提前做好充分的预习,争取做的更好。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 读者 问题 操作系统 实验 报告
![提示](https://static.bingdoc.com/images/bang_tan.gif)