学号:课程设计课程名称操作系统学院计算机科学与技术学院专业软件工程专业班级姓名指导教师2014——2015学年第1学期目录目录 ....................................................................................................................................... 错误!未定义书签。
1 设计概述 (3)1.1问题描述: (3)1.2问题解读及规则制定 (3)2课程设计目的及功能 (3)2.1 设计目的 (3)2.2 设计功能 (3)3模块介绍 (3)3.1函数原型 (3)3.2 PV操作代码 (4)4测试用例,运行结果与运行情况分析 (6)4.1测试用例 (6)4.2运行结果 (7)4.3运行情况分析 (9)5自我评价与总结 (9)6 参考文献 (10)7 附录:(完整代码) (10)实现读者写者(Reader-Writer Problem)问题1 设计概述1.1问题描述:通过研究Linux的线程机制和信号量实现读者写者(Reader-Writer)问题并发控制。
1.2问题解读及规则制定一个数据文件或记录可被多个进程所共享,我们将其中只要求读该文件的进程称为读者,其他进程称为写者.多个读者和多个写者进程在某个时间段内对该文件资源进行异步操作,也就是说允许多个进程同时读一个共享对象,但不允许一个写进程和其他读进程或写进程同时访问共享对象,因此,所谓"读者--写者问题"就是指必须保证一个写进程和其他进程(写进程或者读进程)互斥地访问共享对象的同步问题.两者的读写操作限制规则如下:(1)写--写互斥,即不允许多个写着同时对文件进行写操作(2)读--写互斥,即不允许读者和写者同时对文件分别进行读写操作(3)读—读允许,即允许多个读者同时对文件进行读操作2课程设计目的及功能2.1 设计目的通过实验模拟读者和写者之间的关系,了解并掌握他们之间的关系及其原理。
由此增加对进程同步的问题的了解。
具体如下:1)掌握基本的同步互斥算法,理解读者和写者模型2)了解多线程的并发执行机制,线程间的同步和互斥2.2 设计功能:利用模拟用信号量机制实现读者和写者问题:通过用户控制读进程和写进程,反应读者和写者问题中所涉及的进程的同步与互斥。
3模块介绍3.1函数原型读者和写者进程由11个函数组成,分别如下: (附件包含全部具体实现)void P_write(int);void write(int);void V_write(int);void P_radd(int);void radd(int);void P_read(int);void V_radd(int);void read(int);void P_rsub(int);void rsub(int);void V_read(int);void V_rsub(int);3.2 PV操作代码:模拟写者对Wmutex的P操作,同时为写者进程也作写的入口:void P_write(int i){Wmutex--;if(Wmutex<0){w_wait[-Wmutex-1]=i;}elsewrite(i);}模拟写者对Wmutex的V操作,写操作完成的时候调用:void V_write(int i){w[i]=0;Wmutex++;if(Wmutex<=0){int k,j;if((w_wait[0]>=0)&&(w_wait[0]<w_num)){j=w_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];write(j);}else{j=r_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];V_radd(j);}}}模拟读之前对Rmutex的P操作,同时也作为读者进程的入口:void P_radd(int i) {Rmutex--;if(Rmutex<0){r_wait[-Rmutex]=i;}elseradd(i);}模拟读者对Wmutex的P操作:void P_read(int i){Wmutex--;if(Wmutex<0){w_wait[-Wmutex-1]=10;r_wait[0]=i;}elseV_radd(i);}模拟读之前对Rmutex的V操作:void V_radd(int i){Rmutex++;if(Rmutex<=0){int k,j;j=r_wait[0];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];radd(j);}read(i);}模拟读之后对Rmutex的P操作,读操作完成的时候调用:void P_rsub(int i){r[i]=0;Rmutex--;rsub(i);}模拟读者对Wmutex的V操作:void V_read(int i) {Wmutex++;if(Wmutex<=0){int k,j;if((w_wait[0]>=0)&&(w_wait[0]<w_num)){j=w_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];write(j);}else{j=r_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];V_radd(j);}}V_rsub(i);}模拟读之后对Rmutex的V操作:void V_rsub(int i){Rmutex++;}4测试用例,运行结果与运行情况分析4.1测试用例测试用例如下:1、输入写者个数:42、输入读者个数:23、写者1申请写操作,此时状态:写者1正在写4、读者1申请读操作,此时状态:写着1正在写,读者1等待6、写者1完成写操作,此时状态:读者1正在读7、读者2申请读操作,此时状态:读者1正在读,读着2正在读8、写者3申请写操作,此时状态:读者1正在读,读者2正在读,写着3等待9、读者1完成读操作,此时状态:读者2正在读,写着3等待10、读者2完成读操作,此时状态:写者3正在写11、写者2申请写操作,此时状态:写者3正在写,写者2等待12、写者3完成写操作,此时状态:写者2正在写13、写者2完成写操作,此时状态:无读无写14、写者4申请写操作,此时状态:写者4正在写15、读者1申请读操作,此时状态:写着4正在写,读者1等待16、读者2申请读操作,此时状态:写着1正在写,读者1等待,读者2等待17、写者4完成写操作,此时状态:读者1正在读,读者2正在读18、结束4.2运行结果运行结果如图:4.3运行情况分析当有读者对文件读时,写操作等待,读操作执行当有写者对文件写时,读操作等待,写操作等待完全符合限制规则及实际应用5自我评价与总结本次设计中,用C++编程模拟了用信号量机制实现读者和写者问题。
总的来说,通过本次设计收获很大。
读者和写者问题,一直认为这些东西很简单,但是具体编程实现其模拟并不容易。
虽然这还不算真正的实践,但通过这次设计,向实践靠近了一步。
更加深刻的理解了操作系统中这些理论知识的意义。
同时也让我温习以前所学习的高级语言。
6 参考文献[1] 报刊《计算机教育》文章编号1672-5913(2011)22-0056-03,《操作系统课程之“读者-写着”问题教学探讨》[2] 严蔚敏,吴伟民著,数据结构(c++版)北京:清华大学出版社,20077 附录:(完整代码)#include<iostream>int r_num;//读者个数int w_num;//写者个数int Wmutex=1;//表示允许写或允许读int readCount=0;//表示正在读的进程数int Rmutex=1;//表示对Rcount的互斥操作int r[10]={0,0,0,0,0,0,0,0,0,0};//表示读者的状态,1表示正在读int w[10]={0,0,0,0,0,0,0,0,0,0};//表示写者的状态,1表示正在写int w_wait[11]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};//表示等待队列,0-9表示写者,10时需引入读者的等待队列,-1表示空int r_wait[11]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};//读者的等待队列,0-9表示对应的读者,-1为空void P_write(int);//模拟写者对Wmutex的P操作,同时也作为写者进程的入口void write(int);//开始写操作void V_write(int);//模拟写者对Wmutex的V操作,写操作完成的时候调用void P_radd(int);//模拟读之前对Rmutex的P操作,同时也作为读者进程的入口void radd(int);//readCount加1void P_read(int);//模拟读者对Wmutex的P操作void V_radd(int);//模拟读之前对Rmutex的V操作void read(int);//读操作void P_rsub(int);//模拟读之后对Rmutex的P操作,读操作完成的时候调用void rsub(int);//readCount减1void V_read(int);//模拟读者对Wmutex的V操作void V_rsub(int);//模拟读之后对Rmutex的V操作void P_write(int i){Wmutex--;if(Wmutex<0) //表示如果Wmutex<0,则该写者进入等待队列{w_wait[-Wmutex-1]=i;}elsewrite(i);}void write(int i){w[i]=1;}void V_write(int i){w[i]=0;Wmutex++;if(Wmutex<=0) // 表示如果Wmutex<=0,则从等待队列中选择写者或读者进行操作{int k,j;if((w_wait[0]>=0)&&(w_wait[0]<w_num)){j=w_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];write(j);}else{j=r_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];V_radd(j);}}}void P_radd(int i) {Rmutex--;if(Rmutex<0) // 表示如果Rmutex<0,则进入等待队列{r_wait[-Rmutex]=i;}elseradd(i);}void radd(int i){readCount++;if(readCount==1)P_read(i);elseV_radd(i);}void P_read(int i){Wmutex--;if(Wmutex<0) // 表示如果Wmutex<0,则进入等待队列{w_wait[-Wmutex-1]=10;r_wait[0]=i;}elseV_radd(i);}void V_radd(int i){Rmutex++;if(Rmutex<=0) //表示如果Rmutex<=0,则从等待队列中选择读者进入readCount的临界区{int k,j;j=r_wait[0];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];radd(j);}read(i);}void read(int i){r[i]=1;}void P_rsub(int i){r[i]=0;Rmutex--;rsub(i);}void rsub(int i){readCount--;if(readCount==0)V_read(i);elseV_rsub(i);}void V_read(int i) {Wmutex++;if(Wmutex<=0) //表示如果Wmutex<=0,则从等待队列中选择写者或读者进行操作{int k,j;if((w_wait[0]>=0)&&(w_wait[0]<w_num)){j=w_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];write(j);}else{j=r_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];V_radd(j);}}V_rsub(i);}void V_rsub(int i){Rmutex++;}int main(){using namespace std;cout<<"请输入写者个数(1到10):";cin>>w_num;while(w_num<1||w_num>10){cout<<"输入有误,请重新输入写者个数(1到10):";cin>>w_num;}//完成对写者个数的输入cout<<"请输入读者个数(1到10):";cin>>r_num;while(r_num<1||r_num>10){cout<<"输入有误,请重新输入读者个数(1到10):";cin>>r_num;}//完成对读者个数的输入int x,k,j,a[20];while(1){cout<<"----------------------------------------------------------------------"<<endl;for(k=0;k<20;k++) a[k]=0;cout<<"Wmutex="<<Wmutex<<"readCount="<<readCount<<"Rmutex="<<Rmutex<<endl;for(k=0;k<w_num;k++){if(w[k]==1)cout<<"-------写者"<<(k+1)<<"正在写"<<endl;}for(k=0;k<r_num;k++){if(r[k]==1)cout<<"-------读者"<<(k+1)<<"正在读"<<endl;}if(w_wait[0]==-1) cout<<"等待队列中无对象"<<endl;else{cout<<"等待队列中有:";for(k=0;k<w_num;k++){if(w_wait[k]==10)for(j=0;j<5;j++){if(r_wait[j]!=-1)cout<<"-->"<<"读者"<<(r_wait[j]+1);}if((w_wait[k]>=0)&&(w_wait[k]<w_num))cout<<"-->"<<"写者"<<(w_wait[k]+1);}cout<<endl;}for(k=0;k<w_num;k++){x=0;for(j=0;j<w_num;j++){if(k==w_wait[j]){a[k]=1;x=1;}}if(x==1) continue;cout<<"("<<(k+1)<<")写者"<<(k+1);if(w[k]==0) cout<<"申请";else cout<<"完成";}for(k=0;k<r_num;k++){x=0;for(j=0;j<r_num;j++){if(k==r_wait[j]){a[k+w_num]=1;x=1;}}if(x==1) continue;cout<<"("<<(k+1+w_num)<<")读者"<<(k+1);if(r[k]==0) cout<<"申请";else cout<<"完成";}cout<<"("<<(w_num+r_num+1)<<")结束"<<endl;cout<<"请输入选项序号:";cin>>x;while(x<1||x>(w_num+r_num+1)||a[x-1]==1){if(a[x-1]==1) cout<<"该对象已在等待队列中,请重新输入:";else cout<<"输入有误,请重新输入:";cin>>x;}for(k=0;k<w_num;k++){if(x==(k+1)){if(w[k]==0) P_write(k);else V_write(k);break;}}for(k=0;k<r_num;k++){if(x==(k+1+w_num)){if(r[k]==0) P_radd(k);else P_rsub(k);break;}}if(x==(w_num+r_num+1)) return 0;}}。