当前位置:文档之家› 读者写者问题-操作系统实验报告

读者写者问题-操作系统实验报告

实验内容1、定义一个数据缓存buffer 及用于实现同步互斥的信号量。

2、定义一个读者函数:当有写者在占用buffer 时,读者应该等待,直到写者不再使用该buffer。

当有其他读者在占用buffer 时,读者可对buffer 进行读取操作。

当buffer 中有数据时,则从其中读取一个数据,并显示然后退出。

当buffer 中没有数据时,应等待,直到buffer 中有数据可读。

3、定义一个写者函数当有读者在占用buffer 时,写者应该等待,直到所有的读者都退出为止。

当有其他写者占用buffer 时,该写者应该等待,直到占用buffer 的写者退出为止。

当buffer 有空闲时,写者应该在buffer 中写入一个数据并退出。

当buffer 满时,写者应该等待,直到buffer 有空闲为止。

4、定义主函数,在其中可以任意创建读者与写者。

可根据用户输入创建读者或写者进程(线程)。

5、用户界面写出的内容:实验当堂所要完成事情列表:1. 调试程序使其在读者优先模式下可以运行并且能实现基本的功能得出正确的结果:能够实现读写互斥,写写互斥,读读不互斥,一个进程结束能够唤醒等待队列中的进程(先读者队列后写着队列)2. 根据实验要求完善功能:由用户决定写者向缓冲区中写入的内容,读者能够读出并显示出来;当缓冲区中没有数据时,读者要等待,直到缓冲区中有数据才能读3. 根据“读者优先”加以改变,增加一个“写者优先”模式,并且由用户来选择模式源代码:#include<stdio.h>#include<stdlib.h>int rcount=0;// int wcount=0;// int read_id=0;// int write_id=0;// 正在读的读者数量写者队列中等待写操作的写者数量读进程号写进程号int w=1;// 读写互斥信号量char temp[300] = {'\0'};int choice; // 用户选择读者优先OR写者优先int sign; // 标识temp 空的信号量0 表示temp 空void WFwakeup(); void RFwakeup();struct rqueue{// 读者等待队列int readers[200];int index;}rq;struct wqueue{// 写者等待队列int writers[200];int index;}wq;/*void first(){ // 初始化int i;rq.index = 0;wq.index = 0;for(i = 0;i<20;i++){ rq.readers[i] = 0; wq.writers[i] = 0;}}*///******************************************* 读进程读操作void read(){int i = 0;read_id++;if(rcount == 0){// 当前没有读进程在读可能有写进程在写可能CPU空闲if(w==1) {// 如果CPU空闲,读者拿到CPUw--;// 相当于一个P 操作rcount++; if(temp[0] == '\0'){ sign = 0; if(choice ==1){ rq.readers[rq.index++]=read_id;// 将读者进程加入等待队列RFwakeup(); return;} else{ rq.readers[rq.index++]=read_id;// 将读者进程加入等待队列WFwakeup(); return;}}//ifprintf(" 读者%d正在读\n",read_id);for(i = 0;i < 300;i++){// 读取temp内容即写者写的内容if(temp[i] == '\0'){printf("\n"); return;}//if printf("%c",temp[i]);}//for}//if else{// 写者线程正在执行printf(" !有写者在写不能读!\n");rq.readers[rq.index++]=read_id;// 将读者进程加入等待 队列 }//else }//ifelse{//rcount !=1 则知道当前已经有读者在读,读读不互斥,则这 个读者可以直接进来了读printf(" 读者 %d 正在读 \n",read_id); for(i = 0;i < 300;i++){if(temp[i] == '\0'){ printf("\n"); return; }printf("%c",temp[i]);}//for }//else}//*************************** void write(){ write_id++;if(w == 0){ if(rcount != 0 ){//printf(" !有读者在读不能写! \n");wq.writers[wq.index++]=write_id;// 将写者进程加入等待 队列 wcount++; return;}if(rcount == 0 ){//rcount == 0 则当前无读者,但 w = 0 ,所以有写者在写printf(" !有写者在写不能写! \n");wq.writers[wq.index++]=write_id;// 将写者进程加入等待 队列wcount++; return;}}if(w == 1){w--;printf(" 写者 %d 正在写 \n 请输入要写的内容 ",write_id); scanf("%s",temp); //while }//if写进程写操作有读者进程在执行}//************************ voidRFwakeup(){int i = 0; int j = 0; int m,n;m = rq.index; // n = wq.index;if(rcount == 0){// 当前无读进程,是写者在写 程 bool reader_wait=false; w=1;printf(" 写者已经写完 \n");sign = 1;//temp 中已经有内容 要置 1for(i=0;i<=m;i++){// i ndex 为当前读者队列中的等待进程数if(rq.readers[i]!=0){reader_wait=true; // 确实有读者在等待 printf(" 等待的读者 %d正在读 \n",rq.readers[i]); w = 0;for(j = 0;j < 300;j++){if(temp[j] == '\0'){printf("\n"); break;}//if printf("%c",temp[j]);}//for rq.readers[i]=0; rcount++; rq.index--;}//if }//forif(!reader_wait){// 没有读者等待,看是否有写者等待 for(inti=0;i<=wq.index;i++){//检查写者等待队列if(wq.writers[i]!=0){w = 0;printf(" 等待的写者 %d 正在写 \n 请输入要写入的内 容",wq.writers[i]);scanf("%s",temp); wq.writers[i]=0; wcount--; break;读者优先时唤醒进程-- 》停止运行写进}//if }//for }//if // return; }//ifelse{//rcount != 0 读者正在读, stop 读 此时若有等待必为写 者rcount=0; w = 1;if(sign == 0){printf(" 缓冲区空 等待写者 \n"); return;}else{printf(" 读者已经读完 \n");for(int i=0;i<=wq.index;i++){// if(wq.writers[i]!=0){ w = 0;printf(" 等待的写者 容",wq.writers[i]);scanf("%s",temp); wq.writers[i]=0; wcount--; break;}//if }//for}}//else}//****************************************** void WFwakeup(){int i = 0; int j = 0; int m,n;m = rq.index; //n = wq.index;if(rcount == 0){// 当前无读进程, 程bool writer_wait=false; w=1; printf(" 写者已经写完 \n");sign = 1;//temp 中已经有内容 要置1 for(i=0;i<=wq.index;i++){// index 为当前写者队列中的等 待进程数if(wq.writers[i]!=0){writer_wait=true; // 确实有写者在等待 printf(" 等待的写者 %d 正在写 \n 请输入要写的内容 \n",wq.writers[i]);w = 0;scanf("%s",temp); wq.writers[i]=0; wcount--;检查写者等待队列%d 正在写 \n 请输入要写入的内写者优先唤醒是写者在写 -- 》停止运行写进break;}}if(!writer_wait){// 没有xie 者等待,看是否有du 者等待for(inti=0;i<=m;i++){// 检查写者等待队列if(rq.readers[i]!=0){w = 0;printf(" 等待的读者%d正在读\n",rq.readers[i]);for(j = 0;j < 300;j++){if(temp[j] == '\0'){ printf("\n"); rq.index--; break;}//ifprintf("%c",temp[j]);}//forrq.readers[i]=0; rcount++;}//if}//for}//if// return;}//ifelse{//rcount != 0 读者正在读,stop 读此时若有等待必为写者rcount=0;w = 1;printf(" 读者已经读完\n");for(int i=0;i<=wq.index;i++){// 检查写者等待队列if(wq.writers[i]!=0){ w = 0;printf(" 等待的写者%d正在写\n 请输入要写入的内容",wq.writers[i]);scanf("%s",temp);wq.writers[i]=0;wcount--;break;}//if}//for}}void menu1(){char i;结束当前执行的printf(" 1- 创建读者进程\n 2- 创建写者进程\n 3- 进程\n 4- 退出程序\n");printf(" **\n");do{%d个printf(" 当前队列中有读者:%d 个写者:\n",rq.index,wcount);printf(" **\n");printf(" ---- >");scanf("%s",&i);switch(i){case '1':read();break; case'2':write();break; case'3':RFwakeup();break;case '4':exit(0);default:printf(" } }while(true)输入错误请重新输入\n");;}void menu2(){char i;结束当前执行的printf(" 1- 创建读者进程\n 2- 创建写者进程\n 3- 进程\n 4- 退出程序\n");printf(" **\n");do{printf(" 当前队列中有读者:%d 个写者:%d个\n",rq.index,wcount);printf("*******************************************\n");printf(" ---- >");scanf("%s",&i);switch(i){case '1':read(); break; case '2':write();break;case '3':WFwakeup(); break;case '4':exit(0);default:printf(" 输入错误请重新输入\n");}}while(true);}void main(){printf("printf(" 20092104\n 2. 写者优先\n");scanf("%d",&choice);while(1){if(choice == 1) menu1();if(choice == 2)menu2();if(choice != 1 && choice != 2){ printf(" 输入错误请重新输入\n"); scanf("%d",&choice);实验一\n 1 读者优先}Y 当前有无读者在读 N 有无读者等待 Y 读者出队进行读操作直到读者队空 有无写者等待 Y N 进行写操作 N 缓冲区是否为空 返回 Y 写者优先唤醒 当前有无读者在读 N 有无写者等待 Y 写者出队进行写操作直到写者队空 有无读者等待 Y 进行读操作直到读者队列为空 写者队列是否为空返回 读者优先唤醒 有读者说明若有等待必为写者核心部分设计思路:分别用两个队列来存放等待的读者进程和写者进程,一个进程结束后就要将因他阻塞的进程唤醒,如果是读者优先,则先检查读者进程,如果发现读者进程不为空,就进行读操作,直到读者进程为空,才进行写操作;同理,如果是写者优先,则先检查写进程,如果发现写者进程不为空,就进行写操作,直到写者进程为空,才进行读操作。

相关主题