淮北师范大学课程设计采用读写平等策略的读者写者问题学号:姓名:专业:指导教师:日期:目录第1部分课设简介 (3)1.1 课程设计题目 (3)1.2 课程设计目的.................. 错误!未定义书签。
1.3 课程设计内容 (3)1.4 课程设计要求 (4)1.5 时间安排 (4)第2部分实验原理分析 (4)2.1问题描述 (4)2.2算法思想 (5)2.3主要功能模块流程图 (5)第3部分主要的功能模块 (6)3.1数据结构 (6)3.2测试用例及运行结果 (7)第4部分源代码 (7)第5部分总结及参考文献 (22)5.1 总结 (22)5.2 参考文献 (23)第1部分课设简介1.1 课程设计题目采用读写平等策略的读者写者问题1.2课程设计目的操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决实际问题的机会。
1)进一步巩固和复习操作系统的基础知识。
2)培养学生结构化程序、模块化程序设计的方法和能力。
3)提高学生调试程序的技巧和软件设计的能力。
4)提高学生分析问题、解决问题以及综合利用C语言进行课程设计的能力。
1.3课程设计内容用高级语言编写和调试一个采用“读写平等”策略的“读者-- 写者”问题的模拟程序。
1.4课程设计要求1)读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入。
2) 读者与写者均有两个以上,可在程序运行期间进行动态增加读者与写者。
3)可读取样例数据(要求存放在外部文件中),进行读者/写者、进入内存时间、读写时间的初始化。
4) 要求将运行过程用可视化界面动态显示,可随时暂停,查看阅览室中读者/写者数目、读者等待队列、读写时间、等待时间。
5) 读写策略:读写互斥、写写互斥、读写平等(严格按照读者与写者到达的顺序进入阅览室,有写着到达,则阻塞后续到达的读者;有读者到达,则阻塞后续到达的写者)。
1.5时间安排1)分析设计贮备阶段(1 天)2)编程调试阶段(7 天)3)写课程设计报告、考核(2 天)第2部分实验原理分析2.1问题描述有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间,甚至可以是一组处理器寄存器。
有一些只读取这个数据区的进程reader和一些只往数据区中写数据的进程writer 以下假设共享数据区是文件。
这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。
这些条件具体来说就是:1)任意多的读进程可以同时读这个文件;2)一次只允许一个写进程往文件中写;3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;4)写进程执行写操作前,应让已有的写者或读者全部退出。
这说明当有读者在读文件时不允许写者写文件。
2.2算法思想三个线性链表,分别为h1、h2、h3。
h1为写入序列,h2为就绪序列,h3为执行序列。
其中h1用来存放输入进去的读者和写者的信息,h2根据读入内存的时间将h1中的读者写者的信息进行排序,并将排完序的读者与写者信息存在h2中,把h2的内容调入到执行序列h3中,从而执行要求的内容。
2.3主要功能模块流程图第3部分主要的功能模块3.1 数据结构主要的数据结构及数据:int Wmutex=1;//互斥读写的信号量int readcount=0; //读者数目struct process//进程结构体{int ID; //进程序号char type; //进程类别(判断是读者还是写者)int starttime; //进程开始时间int needtime; //进程读写需要的时间int runtime; //进程在内存中已运行的时间struct process *next;};process *h1=NULL,*h2=NULL,*h3=NULL;//三个链表函数成员:void input()//输入信息函数void main()//主函数void choose()//选择函数void ready(int i)//进入就绪队列函数int wait(int &a)//等待队列函数void reader()//读写平等下的读者信息函数void writer()//读写平等下的写者信息函数void add(int i)//动态增加函数void print(int i)//输出函数void leave()//离开执行队列3.2测试用例及运行结果运行程序进入界面后,选择1,运行界面如图1-1;选择2,运行完后查看文件显示如图1-2;选择3查看信息,运行界面如图1-3;在执行过程中按下s可以暂停进程的执行,在进程暂停的情况下,按下a可以增加进程,运行结果如图1-4所示。
图1-1图1-2图1-3图1-4第4部分源代码#include <stdio.h>#include <stdlib.h>#include <conio.h>#include "windows.h"int Wmutex=1;//互斥读写的信号量int readcount=0; //读者数目void input();void main();struct process{int ID; //进程序号char type; //进程类别(判断是读者还是写者)int starttime; //进程开始时间int needtime; //进程读写需要的时间int runtime; //进程在内存中已运行的时间struct process *next;};process *h1=NULL,*h2=NULL,*h3=NULL;void choose()//选择{int a;process *p,*q;q=h1=(process *)malloc(sizeof(process));FILE *fp;scanf("%d",&a);switch(a){case 1: //手动输入int i,j;printf("\t\t输入进程数:");fp=fopen("","w+");scanf("%d",&i);fprintf(fp,"%d\n",i);for(j=1;i>0;i--,j++){p=(process *)malloc(sizeof(process));q->next=p;printf("\t\t第%d个进程:\n",j);printf("\t\t进程序号\t读或写\t\t开始时间\t执行时间\n\t\t");scanf("%d %c %d %d",&p->ID,&p->type,&p->starttime,&p->needtime);fprintf(fp,"%d %c %d %d\n",p->ID,p->type,p->starttime,p->needtime);printf("\n");p->runtime=0;q=q->next;p->next=NULL;}fclose(fp);p=h1;h1=h1->next;p->next=NULL;free(p);break;case 2: //文件读入if((fp=fopen("","r"))==NULL){printf("文件打开失败!\n");system("pause");system("cls");main();}fscanf(fp,"%d",&i);for(j=1;i>0;i--,j++){p=(process *)malloc(sizeof(process));q->next=p;fscanf(fp,"%d %c %d %d",&p->ID,&p->type,&p->starttime,&p->needtim e);p->runtime=0;q=q->next;p->next=NULL;}fclose(fp);p=h1;h1=h1->next;p->next=NULL;free(p);break;case 3:int k;if((fp=fopen("","r"))==NULL){printf("文件打开失败!\n");system("pause");system("cls");main();}printf("\t\t进程序号\t读或写\t\t开始时间\t执行时间\n");fscanf(fp,"%d",&i);k=0;for(j=0;i>0;i--,j++){p=(process *)malloc(sizeof(process));q->next=p;fscanf(fp,"%d %c %d %d",&p->ID,&p->type,&p->starttime,&p->needtimif(p->type=='r'||p->type=='R'){k++;}printf("\t\t%d\t\t%c\t\t%d\t\t%d\n",p->ID,p->type,p->starttime,p->n eedtime);p->runtime=0;q=q->next;p->next=NULL;}j=j-k;printf("\t\t读者数目:");printf("\t%d\n",k);printf("\t\t写者数目:");printf("\t%d\n",j);fclose(fp);p=h1;h1=h1->next;p->next=NULL;free(p);system("pause");system("cls");main();break;case 4:exit(0);default :printf("\t\t您输入的有错误,请重新输入:\n");system("pause");system("cls");main();}void input() //输入函数{printf("\t\t***********读写平等策略*********\n");printf("\t\t\t1.请输入进程信息\n");printf("\t\t\t2.文件载入进程信息\n");printf("\t\t\t3.查看进程信息\n");printf("\t\t\t4.退出\n");printf("\t\t************************************\n");printf("\t\t请选择:");choose();}void ready(int i) //进入就绪队列{process *p,*q,*j,*k;p=h1;q=h2;int t=0;if(h2==NULL){q=h2=(process *)malloc(sizeof(process));q->next=NULL;t=1;}else{while(q->next!=NULL){q=q->next;}}j=(process *)malloc(sizeof(process)); j->next=head1;while(h1->starttime==i){q->next=head1;h1=h1->next;q=q->next;q->next=NULL;j->next=head1;if(h1==NULL)break;}p=h1;while(p!=NULL){if(p->starttime==i){k=j;while(k->next!=p){k=k->next;}k->next=p->next;q->next=p;q=q->next;p=p->next;q->next=NULL;}else{p=p->next;}}h1=j->next;j->next=NULL;free(j);if(t==1){p=h2;h2=h2->next;p->next=NULL;free(p);}}int wait(int &a){a--;if(a<0){return 0;}return 1;}void signal(int &a){a++;}void reader() //读写平等下的读者信息{process *p;int t=0;p=h3;if(h3==NULL){p=h3=(process *)malloc(sizeof(process));p->next=NULL;t=1;}else{while(p->next!=NULL){p=p->next;}}if(readcount>0){p->next=h2;h2=h2->next;p=p->next;p->next=NULL;readcount++;}if((readcount==0)&&(wait(Wmutex)==1)) {p->next=h2;h2=h2->next;p=p->next;p->next=NULL;readcount++;}else Wmutex++;if(t==1){p=h3;h3=h3->next;p->next=NULL;free(p);}}void writer() //读写平等下的写者信息{if((wait(Wmutex)==1)&&(head3==NULL)) {h3=h2;h2=h2->next;h3->next=NULL;}else Wmutex++;}void add(int i) //动态增加{process *p,*q;int a;p=head1;q=(process *)malloc(sizeof(process));printf("\t\t进程序号:");scanf("%d",&q->ID);printf("\t\t\t读或写:");fflush(stdin);scanf("%c",&q->type);printf("\t\t开始时间:");scanf("%d",&a);q->starttime=a+i;printf("\t\t执行时间:");scanf("%d",&q->needtime);q->runtime=0;q->next=NULL;if(h1!=NULL){while(p->next!=NULL)p=p->next;p->next=q;}elseh1=q;}void print(int i) //输出函数{process *p;p=h3;while(p!=NULL){p->runtime++;p=p->next;}printf("\n\t\t执行 %d :\n",i);printf("\t\t执行队列: ");p=h3;if(p==NULL)printf("<空>");elsewhile(p!=NULL){printf("%d ",p->ID);p=p->next;}printf("\n\t\t等待队列: ");p=h2;if(p==NULL)printf("<空>");elsewhile(p!=NULL){printf("%d",p->ID);p=p->next;}printf("\n");}void leave() //离开执行队列{process *p,*q;p=q=(process *)malloc(sizeof(process));p->next=NULL;while(h3!=NULL){if(h3->needtime!=h3->runtime){p->next=h3;p=p->next;}else{if((h3->type=='r')||(h3->type=='R')){ readcount--;if(readcount==0)Wmutex=1;}elsesignal(Wmutex);}h3=h3->next;p->next=NULL;}h3=q->next;q->next=NULL;free(q);}void main(){int i=0;input();while((h1!=NULL)||(h2!=NULL)||(h3!=NULL)) {i++;if(h1!=NULL)ready(i);if(h2!=NULL)while(h2->type=='r'){reader();if(h3!=NULL)if(h3->type=='w')break;if(h2==NULL)break;}if(h2!=NULL)if(h2->type=='w'){writer();}print(i);leave();Sleep(1000); //交出线程占用CPU时间一秒钟fflush(stdin);//清空缓冲区char ch=' ';if (kbhit()==1)//检查当前是否有键盘输入,若有则返回一个非0值,否则返回0{ch=getch();if((ch=='S')||(ch=='s')){printf("\t\t已暂停,任意键继续...\n添加新的进程输入a\n");ch=getchar();}}if(ch=='a')add(i);}printf("\n\n\t\t执行完毕\n");system("pause");system("cls");Wmutex=1;readcount=0;main();while(1);}第5部分总结及参考文献5.1 总结通过这次课设,我学到了很多课堂上学不到的知识,这次我做的是平等策略下的读者写者问题,执行读者与写者在公平竞争下的同步进程问题,另外可以实现进程的可视化显示、暂停和动态增加最后退出,实现了报告的要求,同时非常感谢老师的帮助,我会在这次课设之后,继续完善这个程序,提高自己的动手能力和实践能力。