您的当前位置:首页读写者问题

读写者问题

2020-08-15 来源:乌哈旅游
采用“读写平等”策略的“读者--写者”问题

学 院 计算机科学与技术 专 业 学 号 学 生 姓 名 指导教师姓名

2014年3月 19 日

1

目录

第1部分 课设简介 .................................... 3 1.1 课程设计题目 .................................. 3 1.2 课程设计目的 ................. 错误!未定义书签。 1.3 课程设计内容 ................. 错误!未定义书签。 1.4 时间安排 ...................................... 4 第2部分 实验原理分析 ............... 错误!未定义书签。 2.1问题描述 ..................... 错误!未定义书签。 2.2解决办法 ...................................... 4 第3部分 主要的功能模块 .............................. 4 3.1功能流程图 .................................... 5 3.2 测试用例及运行结果 ............................ 6 3.3 结论„„„„„„„„„„„„„„„„„„„„„ 8 第4部分 源代码 ...................................... 8 第5部分 总结及参考文献 ............................. 21 5.1 总结 ......................................... 21 5.2 参考文献 .................................... 21

2

第1部分 课设简介

1.1 课程设计题目

采用“读写平等”的“读者--写者”问题 1.2 课程设计目的

操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决问题的机会。

 进一步巩固和复习操作系统的基础知识。

 培养学生结构化程序、模块化程序设计的方法和能力。  提高学生调试程序的技巧和软件设计的能力。

 提高学生分析问题、解决问题以及综合利用C语言进行程序设计的能

力。

1.3 课程设计内容

用高级语言编写和调试一个采用“读写平等”策略的“读者—写者”问题的模拟程序。

1.读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入。

2.读者与写者均有两个以上,可在程序运行期间进行动态增加读者与写者。 3.可读取样例数据(要求存放在外部文件中),进行读者/写者、进入内存时间、读写时间的初始化。

4.要求将运行过程用可视化界面动态显示,可随时暂停,查看阅览室中读者/写者数目、读者等待队列、读写时间、等待时间。

5.读写策略:读写互斥、写写互斥、读写平等(严格按照读者与写者到达的顺入阅览室,有写着到达,则阻塞后续到达的读者;有读者到达,则阻塞后续到达的写者)。

3

有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间,甚至可以是一组处理器寄存器。有一些只读取这个数据区的进程(reader)和一些只往数据区中写数据的进程(writer)。以下假设共享数据区是文件。这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。这些条件具体来说就是: (1)任意多的读进程可以同时读这个文件; (2)一次只允许一个写进程往文件中写;

(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件; (4)写进程执行写操作前,应让已有的写者或读者全部退出。这说明当有读者在读文件时不允许写者写文件。

1.4 时间安排

1)分析设计贮备阶段 (1 天) 2)编程调试阶段 (7 天) 3)写课程设计报告、考核(2 天) 第

2部分 实验原理分析

2.1 问题描述

读—读允许;读—写互斥;写—写互斥。这些条件具体来说就是: (1)任意多的读进程可以同时读这个文件; (2)一次只允许一个写进程往文件中写;

(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件; (4)写进程执行写操作前,应让已有的写者或读者全部退出。这说明当有读者在读文件时不允许写者写文件。

2.2 解决办法

创建三个线性链表,分别为head1、head2、head3。head1写入序列,head2

为就绪序列,head3为执行序列。其中head1用来存放输入进去的读者和写者的信息,head2根据读入内存的时间将head1中的读者写者的信息进行排序,并将排完序的读者与写者信息存在head2中,把head2的内容调入到执行序列head3中,从而执行要求的内容。

第3部分 主要的功能模块

4

3.1 功能流程图

开始 Jiuxu(int i) type r reader() w writer () runtime++ Y runtime==needtime N i++ 离开head3 head1==Null&head2==Null&head3==Null Y 结束

图1

5

3.2 测试用例及运行结果

(列出对于给定的输入所产生的输出结果。只写出自己所做功能测试结果) 文件为文本文件。文件内容为: 5(表示进程数)

1 r 7 2(表示进程名,进程类型,进程开始时间,进程运行时间) 2 w 2 3(表示进程名,进程类型,进程开始时间,进程运行时间) 3 r 3 4(表示进程名,进程类型,进程开始时间,进程运行时间) 4 r 5 3(表示进程名,进程类型,进程开始时间,进程运行时间) 5 w 6 4(表示进程名,进程类型,进程开始时间,进程运行时间) 程序运行实例如下: 1.选择2,运行界面如下:

2.选择3,运行界面如下:

6

3.在执行过程中按下s可以暂停进程的执行。

4.在进程暂停的情况下,按下a可以增加进程。

7

3.3 结论

程序运行后,可以通过手动输入进程和文件读取进程,并执行读者与写者在公平竞争下的同步进程问题,另外可以实现进程的可视化显示、暂停和动态增加最后退出。完成任务书的要求。

第4部分 源代码

#include #include #include #include \"windows.h\"

int Wmutex=1;//互斥读写的信号量 int readcount=0; //读者数目 void input(); void main(); struct process {

int ID; //进程序号

char type; //进程类别(判断是读者还是写者) int starttime; //进程开始时间 int needtime; //进程读写需要的时间

8

};

int runtime; //进程在内存中已运行的时间 struct process *next;

process *head1=NULL,*head2=NULL,*head3=NULL;

void choose()//选择 {

int a;

scanf(\"%d\

switch(a) {

case 1: //手动输入

int i,j;

printf(\"\\输入进程数:\");

fp=fopen(\"file.txt\scanf(\"%d\

process *p,*q;

q=head1=(process *)malloc(sizeof(process)); FILE *fp;

fprintf(fp,\"%d\\n\

for(j=1;i>0;i--,j++) {

p=(process *)malloc(sizeof(process)); q->next=p;

printf(\"\\第%d个进程:\\n\

printf(\"\\进程序号\读或写\\开始时间\执行时间

\\n\\\");

scanf(\"%d %c %d %d\

fprintf(fp,\"%d %c %d %d\\n\

printf(\"\\n\");

9

}

p->runtime=0; q=q->next; p->next=NULL;

fclose(fp); p=head1;

head1=head1->next; p->next=NULL; free(p); break;

case 2: //文件读入

if((fp=fopen(\"file.txt\

{

printf(\"文件打开失败!\\n\");

system(\"pause\");

system(\"cls\"); main();

}

fscanf(fp,\"%d\

for(j=1;i>0;i--,j++)

{

p=(process *)malloc(sizeof(process)); q->next=p;

fscanf(fp,\"%d %c %d %d\ p->runtime=0;

}

fclose(fp); p=head1;

head1=head1->next; p->next=NULL; free(p);

q=q->next; p->next=NULL;

10

break;

case 3:

int k;

if((fp=fopen(\"file.txt\

{

printf(\"文件打开失败!\\n\");

system(\"pause\");

system(\"cls\"); main();

}

printf(\"\\进程序号\读或写\\开始时间\执行时间\\n\");

fscanf(fp,\"%d\

k=0;

for(j=0;i>0;i--,j++)

{

p=(process *)malloc(sizeof(process));

q->next=p;

fscanf(fp,\"%d %c %d %d\

if(p->type=='r'||p->type=='R')

{

k++;

}

printf(\"\\%d\\%c\\%d\\%d\\n\

p->runtime=0; q=q->next; p->next=NULL;

} j=j-k;

printf(\"\\读者数目:\"); printf(\"\%d\\n\ printf(\"\\写者数目:\");

11

printf(\"\%d\\n\

fclose(fp);

p=head1; }

void input() //输入函数 {

printf(“\\***********读写平等策略*********\\n\"); printf(\"\\\1.人工输入进程信息\\n\"); printf(\"\\\2.文件载入进程信息\\n\");

head1=head1->next; p->next=NULL; free(p);

system(\"pause\");

system(\"cls\"); main();

break;

case 4:

exit(0);

default :

printf(\"\\您输入的有错误,请重新输入:\\n\"); system(\"pause\");

system(\"cls\"); main(); }

printf(\"\\\3.查看进程信息\\n\");

printf(\"\\\4.退出\\n\");

printf(\"\\************************************\\n\"); printf(\"\\请选择:\");

choose(); }

void ready(int i) //进入就绪队列 {

12

process *p,*q,*j,*k; p=head1; q=head2; int t=0; if(head2==NULL) { } else { }

j=(process *)malloc(sizeof(process)); j->next=head1;

while(head1->starttime==i) { } p=head1; while(p!=NULL) {

if(p->starttime==i) {

q->next=head1; head1=head1->next; q=q->next; q->next=NULL; j->next=head1; if(head1==NULL)

break;

while(q->next!=NULL) { }

q=q->next;

q=head2=(process *)malloc(sizeof(process)); q->next=NULL; t=1;

13

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;

}

}

head1=j->next; j->next=NULL; free(j); if(t==1) { p=head2;

head2=head2->next; p->next=NULL; free(p);

}

}

int wait(int &a) { a--; if(a<0) {

return 0;

14

}

}

return 1;

void signal(int &a) { }

void reader() //读写平等下的读者信息 {

process *p; int t=0; p=head3; if(head3==NULL) { } else { }

if(readcount>0) {

p->next=head2; head2=head2->next; p=p->next; p->next=NULL; readcount++;

while(p->next!=NULL) { }

p=p->next;

p=head3=(process *)malloc(sizeof(process)); p->next=NULL; t=1; a++;

15

}

}

if((readcount==0)&&(wait(Wmutex)==1)) { }

else Wmutex++;

if(t==1) { }

p=head3;

head3=head3->next; p->next=NULL; free(p); p->next=head2; head2=head2->next; p=p->next; p->next=NULL; readcount++;

void writer() //读写平等下的写者信息 { }

void add(int i) //动态增加 {

process *p,*q;

if((wait(Wmutex)==1)&&(head3==NULL)) { }

else Wmutex++;

head3=head2; head2=head2->next; head3->next=NULL;

16

int a; p=head1;

q=(process *)malloc(sizeof(process)); printf(\"\\进程序号:\"); scanf(\"%d\ printf(\"\\\读或写:\"); fflush(stdin); scanf(\"%c\ printf(\"\\开始时间:\"); scanf(\"%d\ q->starttime=a+i; printf(\"\\执行时间:\"); scanf(\"%d\ q->runtime=0; q->next=NULL; if(head1!=NULL) { while(p->next!=NULL)

p=p->next;

p->next=q;

} else

head1=q;

}

void print(int i) //输出函数{ process *p; p=head3; while(p!=NULL) { p->runtime++; p=p->next;

}

17

}

void leave() //离开执行队列 {

process *p,*q;

p=q=(process *)malloc(sizeof(process));

p->next=NULL; while(head3!=NULL) {

if(head3->needtime!=head3->runtime) {

printf(\"\\n\\执行 %d :\\n\printf(\"\\执行队列: \"); p=head3; if(p==NULL)

printf(\"<空>\");

else

while(p!=NULL) { }

printf(\"%d \p=p->next;

printf(\"\\n\\等待队列: \"); p=head2; if(p==NULL)

printf(\"<空>\");

else

while(p!=NULL) { }

printf(\"%d\p=p->next;

printf(\"\\n\");

18

}

}

}

p->next=head3; p=p->next;

else { }

head3=head3->next; p->next=NULL;

if((head3->type=='r')||(head3->type=='R')) { } else

signal(Wmutex); readcount--; if(readcount==0)

signal(Wmutex);

head3=q->next; q->next=NULL; free(q);

void main() {

int i=0; input();

while((head1!=NULL)||(head2!=NULL)||(head3!=NULL)) {

i++;

if(head1!=NULL)

ready(i);

if(head2!=NULL)

while((head2->type=='r')||(head2->type=='R')) {

19

}

reader(); if(head3!=NULL)

if((head3->type=='w')||(head3->type=='W'))

break;

if(head2==NULL)

break;

if(head2!=NULL)

print(i);

if((head2->type=='w')||(head2->type=='W')) { }

writer();

leave();

Sleep(1000); //交出线程占用CPU时间一秒钟

fflush(stdin);//清空缓冲区 char ch=' ';

if (kbhit()==1)//检查当前是否有键盘输入,若有则返回一个非0值,

否则返回0

{

ch=getch();

if((ch=='S')||(ch=='s')) {

printf(\"\\已暂停,任意键继续...\\n添加新的进程输入

a\\n\");

}

printf(\"\\n\\n\\执行完毕\\n\");

if((ch=='A')||(ch=='a'))

add(i);

}

}

ch=getchar();

20

system(\"pause\"); system(\"cls\"); Wmutex=1;

readcount=0; }

main(); while(1);

五 总结

5.1 总结

1)多线程编程对于解决一些并发性的问题是很高效的,而且也很必要,现在学会了使用多线程编程,对于以后解决类似的并发性问题(例如网络编程中经常遇到的多客户线程同时访问的问题),都会很有用。

2)虽然我们学习的操作系统理论课里面说多线程间的执行顺序具有随机性和不确定性,但我们毕竟是在一个特定的操作系统平台上实验,Windows 的线程调度机制我是不得而知的,所以出现的一些奇怪的问题也很难调试,只好人为地去

21

因篇幅问题不能全部显示,请点此查看更多更全内容