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

合集下载

操作系统实验报告(读者写着问题,时间片轮转算法,内存的分配,进程的调度)

操作系统实验报告(读者写着问题,时间片轮转算法,内存的分配,进程的调度)

电子科技大学计算机学院实验中心小心计算机专业类课程实验报告课程名称:操作系统学 院:软件学院专 业:软件工程学生姓名:李 希学 号:2010231020018指导教师:丁老师日 期: 2012年5月5日电子科技大学实验报告实验一一、实验名称:进程管理二、实验学时:4三、实验内容和目的:实验内容:(1)进程的创建写一段源程序,创建两个进程,当此程序运行时,在系统中有一个父进程和两个子进程活动。

让每一个进程在屏幕上显示字符。

观察纪录屏幕上的显示结果,然后分析原因。

(2)进程的控制修改编写的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕出现的现象,并分析原因。

实验目的:(1)加深对进程概念的理解,明确进程和程序的区别。

(2)进一步认识并发执行的实质。

(3)分析进程竞争资源现象,学习解决进程互斥的方法。

四、实验原理:利用fork函数来创建子进程,并返回子进程的ID号。

利用lockf函数来实现信号量对进程的资源竞争的调度,和互斥的方法。

五、实验器材(设备、元器件):一台装有VS2010的电脑,操作系统为WIN7.六、实验步骤:(1)先写好2个子进程程序,并且让2个子程序在屏幕上分别打印出A,B(2)父进程创建2个子进程,并在屏幕上打印出C。

(3)观察进程竞争资源的现象。

七、实验数据及结果分析:电子科技大学计算机学院实验中心子进程A的代码:#include<iostream>#include<windows.h>using namespace std;int main(){cout<<"I'm Process A/n"<<endl;return 0;}子进程B的代码:#include<iostream>using namespace std;int main(){cout<<"I'm Process B"<<endl;;return 0;}父进程C的代码://#include "stdafx.h"#include<windows.h>#include<iostream>using namespace std;void print_error(){DWORD nErrorNo = GetLastError ( );LPSTR lpBuffer;FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_FROM_SYSTEM,NULL,nErrorNo,LANG_NEUTRAL,(LPTSTR) & lpBuffer,0 ,NULL );if (lpBuffer == NULL){lpBuffer = "Sorry, cannot find this error info. ";}printf("%s (%d).\n", lpBuffer, nErrorNo);}int fork(const char* pszApplication,HANDLE& hProcess){STARTUPINFO si={sizeof(si)};PROCESS_INFORMATION pi;if(!CreateProcess(pszApplication,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) return -1;else{hProcess=pi.hProcess;return pi.dwProcessId;}}void lockf(HANDLE hObj){DWORD state = WaitForSingleObject(hObj,INFINITE);switch (state){case WAIT_OBJECT_0:printf("\nProcess exit.\n");break;case WAIT_TIMEOUT:printf("\nTime out.\n");break;case WAIT_FAILED:printf("\nWait Failed.\n");print_error();break;}}int main(int argc, char* argv[]){HANDLE hProcess1,hProcess2;int child1=fork("C:\\操¨´作Á¡Â系¦Ì统ª3实º¦Ì验¨¦\\ProcessA\\Debug\\ProcessA.exe",hProcess1);if(-1==child1){cout << "fork error!\n";return -1;}lockf(hProcess1);电子科技大学计算机学院实验中心int child2=fork("C:\\操¨´作Á¡Â系¦Ì统ª3实º¦Ì验¨¦\\ProcessB\\Debug\\ProcessB.exe",hProcess2);if(-1==child2){cout << "fork error!\n";return -1;}cout<<"This is Process C\n";lockf(hProcess2);return 0;}程序运行的结果:八、实验结论、心得体会和改进建议:实验结论:成功的通过了父进程C来创建了2个子进程A,B,并成功的对子进程进行了调度与管理。

读者写者实验报告

读者写者实验报告

读者写者实验报告
读者写者问题是指一个共享固定大小缓冲区的进程间通信问题,其中固定大小的缓冲区被多个读者进程和写者进程所共享。

读者进程从缓冲区中读取数据,而写者进程将数据写入缓冲区。

本实验目的是通过使用互斥锁、条件变量和信号量等同步机制,构建一个读者写者问题的解决方案。

实验环境:
- 操作系统:Linux
-编程语言:C语言
实验步骤:
1.创建共享内存缓冲区,用于读者和写者的数据传递。

2.创建互斥锁,用于保护共享内存缓冲区的访问。

3.创建条件变量,用于读者和写者之间的协调。

4.创建读者进程和写者进程,模拟读者写者的并发操作。

5.在读者进程中,通过互斥锁保护共享内存缓冲区,读取数据,并更新计数器。

6.在写者进程中,通过互斥锁保护共享内存缓冲区,写入数据,并更新计数器。

7.使用条件变量实现读者优先或写者优先的策略。

实验结果:
通过实验,我成功实现了读者写者问题的解决方案。

使用互斥锁可以保护共享资源的访问,防止读者和写者同时访问。

使用条件变量可以实现读者优先或写者优先的策略。

实验总结:
通过本次实验,我深入了解了读者写者问题,并且掌握了使用互斥锁、条件变量和信号量等同步机制来解决读者写者问题的方法。

在实现过程中,我遇到了一些困难,例如死锁和竞争条件等问题。


过调试和改进代码,我成功解决了这些问题,提高了程序的稳定性和性能。

在以后的工作中,我会更加注重并发编程的实践,提高自己解决问题
的能力。

2011211320周俊霞-读者写者问题实验报告(word文档良心出品)

2011211320周俊霞-读者写者问题实验报告(word文档良心出品)

操作系统试验--读者-写者问题周俊霞20112113202011211307班进程同步一.实习要求:本课程实验内容引自《Windows 内核实验教程》(陈向群、林斌等编著,机械工业出版社2002.9)。

在Windows 环境下,创建一个包含n 个线程的控制进程。

用这n 个线程来表示n个读者或写者。

每个线程按相应测试数据文件的要求,进行读写操作。

请用信号量机制分别实现读者优先和写者优先的读者-写者问题。

1.读者-写者问题的读写操作限制:1)写-写互斥;2)读-写互斥;3)读-读允许;2.读者优先的附加限制:如果一个读者申请进行读操作时已有另一读者正在进行读操作,则该读者可直接开始读操作。

写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。

二.测试数据文件格式测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写操作的开始时间和持续时间。

每行测试数据包括四个字段,各字段间用空格分隔。

第一字段为一个正整数,表示线程序号。

第一字段表示相应线程角色,R 表示读者是,W 表示写者。

第二字段为一个正数,表示读写操作的开始时间。

线程创建后,延时相应时间(单位为秒)后发出对共享资源的读写申请。

第三字段为一个正数,表示读写操作的持续时间。

当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。

下面是一个测试数据文件的例子:1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 3三、与实验相关的API 介绍在本实验中可能涉及的API 有:线程控制:CreateThread 完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。

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

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

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

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

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

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

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

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

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

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

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

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

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

5、用户界面2. 写者: 开始 读出的内容: 1. 读者:开始 结束 2 1 读者队列等待结束写出的内容: Hello world !结束实验当堂所要完成事情列表: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;}//ifprintf("%c",temp[i]);}//for}//ifelse{//写者线程正在执行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}//************************读者优先时唤醒进程void RFwakeup(){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;}//ifprintf("%c",temp[j]);}//forrq.readers[i]=0;rcount++;rq.index--;}//if}//forif(!reader_wait){//没有读者等待,看是否有写者等待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}//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("等待的写者%d正在写\n请输入要写入的内容",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中已经有内容要置1for(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--;break;}}if(!writer_wait){//没有xie者等待,看是否有du者等待for(int i=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{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':RFwakeup();break;case '4':exit(0);default:printf("输入错误请重新输入\n");}}while(true);}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("*************************************************** ***********************\n");printf(" 20092104实验一\n 1.读者优先\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 Y开始 读者优先 写者优先 读操作 写操作 是否有读者在读进行读操作 YCPU 是否空闲 缓冲区是否为空有写者 读者入队 N Y 入读者等待队列 调用读者优先唤醒 读操作 N 是否有读者在读 有读者 写者入队 Y N Cpu 是否空闲进行写操作 有写者,写操作入队 YN 退出 结束 读者优先唤醒 写者优先唤醒核心部分设计思路:读者优先唤醒当前有无读者在读有无读者等待N有无写者等待N 读者出队进行读操作直到读者队空Y进行写操作 YN 返回Y缓冲区是否为空YN写者优先唤醒当前有无读者在读有无写者等待N有无读者等待N 写者出队进行写操作直到写者队空Y进行读操作直到读者队列为空YN 返回YN写者队列是否为空进行写操作直到写者队列为空Y有读者说明若有等待必为写者分别用两个队列来存放等待的读者进程和写者进程,一个进程结束后就要将因他阻塞的进程唤醒,如果是读者优先,则先检查读者进程,如果发现读者进程不为空,就进行读操作,直到读者进程为空,才进行写操作;同理,如果是写者优先,则先检查写进程,如果发现写者进程不为空,就进行写操作,直到写者进程为空,才进行读操作。

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

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

《计算机操作系统》实验报告题目读者写者问题学院(部)信息学院专业计算机科学与技术班级、学生姓名学号指导教师(签字)一、《二、问题描述一个数据文件或者记录,可以被多个进程共享,我们把只要求读该文件的进程称为“Reader进程”,其他进程则称为“Writer进程”。

允许多个进程同时读一个共享对象,因为读操作不会是数据文件混乱。

但不允许一个Writer进程和其他Reader进程或者Writer进程同时访问共享对象,因为这种访问将会引起混乱。

所谓“读者——写着问题(Reader—Writer Problem)”是指保证一个Writer进程必须与其他进程互斥地访问共享对象的同步问题三、解决问题为实现Reader与Writer进程间在读或写是的互斥而设置了一个互斥的信号量Wmutex。

另外,在设置一个整型变量Readcount表示正在读的进程数目。

由于只要有一个Reader进程在读,便不允许Writer去写。

因此,仅当Readercount=0时,表示尚无Reader进程在读时,Reader进程才需要进行Wait(wmutex)操作。

若Wait(Wmutex)操作成功,Reader 进程便可去读,相应地,做Readcount+1操作。

同理,仅当Reader进程在执行了Readercount-1操作后其值为0时,才执行Signal(Wmutex)操作,以便让Writer进程写。

又因为Readercount是一个可被多个Reader 进程访问的临界资源,因此也应该为它设置一个互斥信号量rmutex。

四、代码实现1、读者优先#include<iostream>#include<>using namespace std;CRITICAL_SECTION rmutex,wmutex;int wr;$int readernum;DWORD WINAPI reader(LPVOID IpParamter){cout<<"读者申请\n";wr++;EnterCriticalSection(&rmutex);if(readernum==0)EnterCriticalSection(&wmutex);readernum++;cout<<"读者进入成功正在读取\n";LeaveCriticalSection(&rmutex);Sleep(2000);—EnterCriticalSection(&rmutex);readernum--;cout<<"读者退出\n";wr--;if(readernum==0)LeaveCriticalSection(&wmutex);LeaveCriticalSection(&rmutex);return 0;}DWORD WINAPI writer(LPVOID PM){cout<<"写者申请\n";&while(wr!=0){}EnterCriticalSection(&wmutex);cout<<"写者已进入正在写入\n";Sleep(500);cout<<"写者退出\n";LeaveCriticalSection(&wmutex);return 0;}int main(){readernum=0;#wr=0;InitializeCriticalSection(&rmutex);InitializeCriticalSection(&wmutex);HANDLE hr[5];//定义读者线程HANDLE hw[5];//定义写者线程//int thnum;int drn=0; //输入的读者个数int dwn=0; //输入的写者个数cout<<"输入读者写者线程 1代表读者 2代表写者 0代表结束"<<endl;int th[10];int num=0;^cin>>th[num];while(th[num]){if(th[num]==1){drn++;}if(th[num]==2){dwn++;}num++;cin>>th[num];}&int hr1=0,hw1=0;for(int j=0;j!=num;j++){if(th[j]==1){hr[hr1]=CreateThread(NULL,0,reader,NULL,0,NULL);hr1++;}if(th[j]==2){hw[hw1]=CreateThread(NULL,0,writer,NULL,0,NULL);hw1++;}}>WaitForMultipleObjects(drn, hr, TRUE, INFINITE);WaitForMultipleObjects(dwn, hw, TRUE, INFINITE);for(int i=0;i!=drn;i++){CloseHandle(hr[i]);}for(int i=0;i!=dwn;i++){CloseHandle(hw[i]);}DeleteCriticalSection(&rmutex);DeleteCriticalSection(&wmutex);return 0;(}2、写者优先#include<iostream>#include<>using namespace std;CRITICAL_SECTION rmutex,wmutex;int ww;int readernum;DWORD WINAPI reader(LPVOID IpParamter){cout<<"读者申请\n";!while(ww!=0){}EnterCriticalSection(&rmutex);if(readernum==0){EnterCriticalSection(&wmutex);}cout<<"读者进入成功正在读取\n";readernum++;LeaveCriticalSection(&rmutex);Sleep(2000);EnterCriticalSection(&rmutex);-readernum--;if(readernum==0)LeaveCriticalSection(&wmutex);cout<<"读者退出\n";LeaveCriticalSection(&rmutex);return 0;}DWORD WINAPI writer(LPVOID PM){ww++;cout<<"写者申请\n";EnterCriticalSection(&wmutex);{cout<<"写者已进入正在写入\n";Sleep(1000);cout<<"写者退出\n";ww--;LeaveCriticalSection(&wmutex);return 0;}int main(){readernum=0;ww=0;InitializeCriticalSection(&rmutex);|InitializeCriticalSection(&wmutex);HANDLE hr[5];//定义读者线程HANDLE hw[5];//定义写者线程int drn=0; //输入的读者个数int dwn=0; //输入的写者个数cout<<"输入读者写者线程 1代表读者 2代表写者 0代表结束"<<endl;int th[10];int num=0;cin>>th[num];while(th[num]){if(th[num]==1){、drn++;}if(th[num]==2){dwn++;}num++;cin>>th[num];}int hr1=0,hw1=0;for(int j=0;j!=num;j++){if(th[j]==1){》hr[hr1]=CreateThread(NULL,0,reader,NULL,0,NULL);Sleep(10);hr1++;}if(th[j]==2){hw[hw1]=CreateThread(NULL,0,writer,NULL,0,NULL);Sleep(10);hw1++;}}WaitForMultipleObjects(drn, hr, TRUE, INFINITE);*WaitForMultipleObjects(dwn, hw, TRUE, INFINITE);for(int i=0;i!=drn;i++){CloseHandle(hr[i]);}for(int i=0;i!=dwn;i++){CloseHandle(hw[i]);}DeleteCriticalSection(&rmutex);DeleteCriticalSection(&wmutex);return 0;}3、执行结果读者优先在读者优先中先两个读者申请,再一个写者申请,再有两个读者申请。

读者-写者 操作系统实验报告 计算机操作系统

读者-写者 操作系统实验报告 计算机操作系统

4.1实验二:读者写者问题4.1.1实验要求在Windows 环境下,创建一个控制台进程,此进程包含n个线程。

用这n个线程来表示n个读者或写者。

每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。

用信号量机制分别实现读者优先和写者优先的读者-写者问题。

读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。

2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。

3)读-读允许,即可以有一个或多个读者在读。

读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。

写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态才能开始读操作。

运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结果读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。

4.1.2测试数据文件格式测试数据文件包括n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。

每行测试数据包括四个字段,各个字段间用空格分隔。

第一字段为一个正整数,表示线程序号。

第二字段表示相应线程角色,R表示读者,W表示写者。

第三字段为一个正数,表示读写操作的开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的读写申请。

第四字段为一个正数,表示读写操作的持续时间。

当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。

下面是一个测试数据文件的例子:1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 3注意:在创建数据文件时,由于涉及到文件格式问题,最好在记事本中手工逐个键入数据,而不要拷贝粘贴数据,否则,本示例程序运行时可能会出现不可预知的错误。

4.1.3实习分析可以将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。

读者写者问题实验报告

读者写者问题实验报告

读者写者问题实验报告1. 引言读者写者问题是操作系统中的经典同步问题,用于研究多线程环境下对共享资源的访问和保护。

在该问题中,有多个读者和写者同时对一个共享资源进行操作,需要保证并发访问时的正确性和效率。

通过本实验,我们将探讨读者写者问题的解决方案,并比较不同算法的性能差异。

2. 实验目标本实验的主要目标是通过实现和比较不同的读者写者问题算法,深入了解并发访问的挑战和解决方案。

具体而言,我们将研究以下几个方面:•设计并实现读者写者问题的解决方案•比较不同算法的性能差异•分析可能的优化策略3. 实验方法我们将使用Python编程语言来实现读者写者问题的解决方案。

在实验过程中,我们将尝试以下几种常见的算法:3.1. 读者优先算法在读者优先算法中,当有读者在访问共享资源时,其他读者可以同时访问,但写者需要等待。

只有当所有读者完成访问后,写者才能获得访问权限。

3.2. 写者优先算法在写者优先算法中,当有写者在访问共享资源时,其他读者和写者都需要等待。

只有当写者完成访问后,其他读者或写者才能获得访问权限。

3.3. 公平算法在公平算法中,读者和写者的访问权限是公平的,先到先得。

无论读者还是写者,都需要按照到达的顺序依次获取访问权限。

4. 实验步骤下面是我们实施实验的具体步骤:4.1. 实现基本的读者写者问题解决方案我们首先实现基本的读者写者问题解决方案,包括读者和写者的线程逻辑和共享资源的访问控制。

我们将使用互斥锁和条件变量来保证并发访问的正确性。

4.2. 实现读者优先算法在已有的基本解决方案的基础上,我们实现读者优先算法。

我们将通过优化访问控制的逻辑来实现读者优先的特性。

4.3. 实现写者优先算法类似地,我们在基本解决方案的基础上实现写者优先算法。

我们将调整访问控制的逻辑,使得写者优先于其他读者和写者。

4.4. 实现公平算法最后,我们实现公平算法。

我们将结合队列和条件变量等技术来确保读者和写者的访问顺序是公平的。

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

操作系统实验报告_读者写者问题
}
void WP_WriterThread(void * p) //---------------------------写者优先--写者线程
{
HANDLE h_Mutex1;//互斥变量
h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutexl");
HANDLE h_Mutex2;
h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex2");
DWORD wait_for_mutex1; //等待互斥变量所有权
};
void RP_ReaderThread(void * p) //---------------------------读者优先--读者线程
{
HANDLE h_Mutex;//互斥变量
//OpenMutex函数功能:为现有的一个已命名互斥体对象创建一个新句柄
h_Mutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");
(附注释)
#include "stdafx.h"
#include"windows.h"
#include<conio.h>
#include<stdlib.h>
#include<fstream.h>
#include<io.h>
#include<string.h>
#include<stdio.h>
#define READER 'R' //读者
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验内容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 进行读操作直到读者队列为空 写者队列是否为空返回 读者优先唤醒 有读者说明若有等待必为写者核心部分设计思路:分别用两个队列来存放等待的读者进程和写者进程,一个进程结束后就要将因他阻塞的进程唤醒,如果是读者优先,则先检查读者进程,如果发现读者进程不为空,就进行读操作,直到读者进程为空,才进行写操作;同理,如果是写者优先,则先检查写进程,如果发现写者进程不为空,就进行写操作,直到写者进程为空,才进行读操作。

相关文档
最新文档