模拟PV操作同步机构,且用PV操作解决生产者——消费者问题.doc

上传人:scccc 文档编号:13175665 上传时间:2021-12-17 格式:DOC 页数:19 大小:269.50KB
返回 下载 相关 举报
模拟PV操作同步机构,且用PV操作解决生产者——消费者问题.doc_第1页
第1页 / 共19页
模拟PV操作同步机构,且用PV操作解决生产者——消费者问题.doc_第2页
第2页 / 共19页
模拟PV操作同步机构,且用PV操作解决生产者——消费者问题.doc_第3页
第3页 / 共19页
模拟PV操作同步机构,且用PV操作解决生产者——消费者问题.doc_第4页
第4页 / 共19页
模拟PV操作同步机构,且用PV操作解决生产者——消费者问题.doc_第5页
第5页 / 共19页
点击查看更多>>
资源描述

《模拟PV操作同步机构,且用PV操作解决生产者——消费者问题.doc》由会员分享,可在线阅读,更多相关《模拟PV操作同步机构,且用PV操作解决生产者——消费者问题.doc(19页珍藏版)》请在三一文库上搜索。

1、实验四:同步机构实验报告学 院: 专业班级: 姓 名: 学 号:一、实验内容:模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误、实验目的:进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中 的多个进程轮流地占用处理器运行。我们把若干个进程都能进行访问和修改的那些变量称为公共变量。 由于进程 是并发地执行的,所以,如果对进程访问公共变量不加限制, 那么就会产生“与 时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。 为 了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。 一般说, 同步机构是由若干条原语一一同步原语一一所组成。本实验要

2、求学生模拟 PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用三、实验题目:模拟PV操作同步机构,且用PV操作解决生产者一一消费者问题。四、此次用到的数据结构知识如下:typedef struct Pcbchar name10;进程名char state10;运行状态char reaso n 10;/若阻塞,其原因int breakp;/断点保护Pcb,*li nk;struct Pcb *n ext;/阻塞时的顺序进程名状态 等待原因断点 后继进程进程控制块结构定义两个进程:link p1;生产者进程,link c1;消费者进程。pc程序计数器和 link read

3、y;就绪队列,link b_s1; si阻塞队列,link b_s2; s2阻塞队列。五、实验源代码:分为四个头文件。1 、a.h 头文件代码如下:#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#i nclude<stdio.h> /* EOF(=AZ #include<stdlib.h> /* atoi() */或 F6),NULL */#include<io

4、.h> /* eof() */ #include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() */ #include <iostream> using namespace std;#include <time.h>#define BUF 10 /缓存的大小#define MAX 20 /最大可以输入的字符2、b.h 头文件代码如下:/ 数据结构的定义和全局变量进程名运行状态 若阻塞,其原因 断点保护typedef struct Pcbchar name10;

5、/char state10; / char reason10; / int breakp; /struct Pcb *next; /阻塞时的顺序Pcb,*link;int s1,s2; /信号量link p1;/ 生产者进程 link c1;/ 消费者进程 char strMAX; / 输入的字符串 char bufferBUF; / 缓冲池 int len; / 输入长度 int sp=0; /string 的指针 int in=0; / 生产者指针 int out=0; / 消费者指针 char temp; / 供打印的临时产品 char rec_pMAX;/ 生产记录 int rp1=0

6、;/ 生产记录指针 char rec_cMAX;/ 消费记录 int rp2=0;/ 消费记录指针 link ready; / 就绪队列 link b_s1; /s1 阻塞队列 link b_s2; /s2 阻塞队列 int pc; / 程序计数器 int count; / 字符计数器 int con_cnt; /消费计数器3、c.h 头文件代码如下:void init();/初始化void p(int s); /P操作void v(int s); /V操作void block(int s);/阻塞函数void wakeup(int s);/唤醒函数void control(); /处理机调度

7、void processor();/处理机执行void print(); /打印函数void init() / 初始化s1=BUF;s2=0;p1=(link)malloc(sizeof(Pcb);/建立新的结点 , 并初始化为生产者strcpy(p1->name,"Producer");strcpy(p1->state,"Ready");strcpy(p1->reason,"Null");p1->breakp=0;p1->next=NULL;c1=(link)malloc(sizeof(Pcb);/建立

8、新的结点 , 并初始化为消费者strcpy(c1->name,"Consumer");strcpy(c1->state,"Ready");strcpy(c1->reason,"Null");c1->breakp=0;c1->next=NULL;ready=p1;ready->next=c1;/ 初始化为生产进程在前,消费进程在后c1->next=NULL;b_s1=NULL;b_s2=NULL;/ 阻塞进程为 NULLpc=0;con_cnt=0; / 消费计数器void p(int s)if

9、(s=1) /p(s1) s1-; if(s1<0)block(1); / 阻塞当前生产进程elseprintf("t* s1 信号申请成功 !n");ready->breakp=pc; / 保存断点else /p(s2)s2-;if(s2<0)block(2);/ 阻塞当前消费进程elseprintf("t* s2 信号申请成功 !n");ready->breakp=pc; / 保存断点void v(int s)if(s=1) /v(s1)s1+;if(s1<=0)wakeup(1); / 唤醒生产进程 ready->

10、;breakp=pc; / 保存断点 else /v(s2)s2+;if(s2<=0)wakeup(2);/ 唤醒消费进程ready->breakp=pc; / 保存断点void block(int s)/ 阻塞函数的定义link p;int num1=0;int num2=0;if(s=1)/ 生产进程strcpy(p1->state,"Block");/ 改变状态 strcpy(p1->reason,"S1");/ 说明原因 p=b_s1;while(p)num1+;p=p->next;/p的值为NULL表示队尾if(!

11、b_s1)b_s1=p1;elsep=p1;p1->next=NULL;printf("t* p1 生产进程阻塞了 !n");ready->breakp=pc; / 保存断点 ready=ready->next;/ 在就绪队列中去掉 , 指向下一个 num1+;else/ 消费进程strcpy(c1->state,"Block");strcpy(c1->reason,"S2");p=b_s2;while(p) num2+;p=p->next;/p的值为NULL表示队尾if(!b_s2) b_s2=c

12、1;elsep=c1;ready->breakp=pc; / 保存断点 ready=ready->next;/ 在就绪队列中去掉 , 指向下一个 c1->next=NULL;printf("t* c1 消费进程阻塞了 !n");num2+;printf("t* 阻塞的生产进程个数为 :%dn",num1);printf("t* 阻塞的消费进程个数为 :%dn",num2);void wakeup(int s)/ 唤醒函数的定义link p;link q=ready;if(s=1) / 唤醒b_s1队首进程,生产进程队

13、列p=b_s1;b_s1=b_s1->next;/ 阻塞指针指向下一个阻塞进程 strcpy(p->state,"Ready");strcpy(p->reason,"Null");while(q)/ 插入就绪队列q=q->next;q=p;p->next=NULL;printf("t* p1 生产进程唤醒了 !n");else /唤醒b_s2队首进程,消费进程队列 p=b_s2;b_s2=b_s2->next;/ 阻塞指针指向下一个阻塞进程 strcpy(p->state,"Read

14、y"); strcpy(p->reason,"Null");while(q->next)/ 插入就绪队列 q=q->next;q->next=p;p->next=NULL;printf("t* c1 消费进程唤醒了 !n");void control() / 处理器调度程序int rd;int num=0;link p=ready;if(ready=NULL) / 若无就绪进程 , 结束return;while(p) / 统计就绪进程个数num+;p=p->next;/ 最终 p 变为 NULL printf

15、("t* 就绪进程个数为 :%dn",num);time_t t;srand(unsigned) time(&t);rd=rand()%num;/ 随机函数产生随机数if(rd=1)p=ready;ready=ready->next;ready->next=p;p->next=NULL;strcpy(ready->state,"Run");strcpy(ready->next->state,"Ready");elsestrcpy(ready->state,"Run"

16、);pc=ready->breakp;void processor() / 模拟处理器指令执行if(strcmp(ready->name,"Producer")=0) /当前进程为生产者switch(pc)case 0:/produceprintf("t* 生产者生产了字符 %cn",strsp);rec_prp1=strsp;/ 添加到生产记录sp=(sp+1)%len;pc+;ready->breakp=pc; / 保存断点break;case 1: /p(s1)pc+;p(1);break;case 2: /putbufferin

17、=rec_prp1; / 放到缓冲区printf("t* %c 字符成功入驻空缓存 !n",bufferin); rp1+;in=(in+1)%BUF;pc+;ready->breakp=pc; / 保存断点 break;case 3: /v(s2)pc+;printf("t* 释放一个 s2 信号 n");v(2);break;case 4:/goto01printf("t* 生产进程 goto 0 操作 n");pc=0;count-; /剩余字符个数减 1printf("t*剩余字符 count=%d个n&quo

18、t;,count);ready->breakp=pc; / 保存断点if(count<=0) / 生产结束printf("t* 生产者结束生产 !n"); strcpy(p1->state,"Stop"); strcpy(p1->reason,"Null");ready->breakp=-1;ready=ready->next;/ 在就绪队列中去掉else / 当前进程为消费者switch(pc)case 0: /p(s2)pc+;p(2);break;case 1: /getprintf(&quo

19、t;t* 消费者取字符 !n");temp=bufferout;out=(out+1)%BUF;pc+;ready->breakp=pc; / 保存断点break;case 2: /v(s1)pc+;printf("t* 释放一个 s1n");v(1);break;case 3: /consumeprintf("t* 消费了字符 %cn",temp);rec_crp2=temp;/ 添加到消费记录 rp2+;con_cnt+;if(con_cnt>=len)strcpy(c1->state,"Stop");

20、/ 完成态 c1->breakp=-1;return;pc+; ready->breakp=pc; / 保存断点 break;case 4: /goto0 printf("t* 消费进程 goto 0 操作 n"); pc=0;ready->breakp=pc; / 保存断点void print()int i,j;printf(" 生产者消费者模拟 n"); printf("*模拟过程的字符串为 :t");printf("%sn",&str);printf("*已生产 :&quo

21、t;);for(j=0;j<=rp1;j+) printf("%c",rec_pj);printf("n* 空缓存 :"); for(j=rp2;j<=rp1;j+) printf("%c",bufferj);printf("n* 已消费 :"); for(j=0;j<=rp2;j+) printf("%c",rec_cj);printf("n 进程控制块的信息 n"); printf("进程名tt 状态t等待原因t断点n");print

22、f("%st%st%stt%dnn",p1->name,p1->state,p1->reason,p1->b reakp);printf("%st%st%stt%dn",c1->name,c1->state,c1->reason,c1->breakp);printf(" printf("1. 继续 0. 退出 n"); scanf("%d",&i);if(i=0)exit(0);4、main 头文件代码如下:n"#include "

23、;a.h"#include "b.h"#include "c.h"void main()printf("* 生产者消费者模拟 n");printf(" n");printf("* 请输入字符串 :n");scanf("%s",str); /string 数组存放将要产生的字符 len=strlen(str);count=len; / 输入字符的个数init(); / 初始化while(con_cnt<len) / 消费完所有的字符为结束system("

24、;cls"); / 清屏操作printf(" 模拟指令流程n");control(); / processor(); / print(); /处理器调度程序 模拟处理器指令执行 输出显示各个信息printf("n 程序结束 !n");六、运行结果截图:*就莖进程个*生弄者生产生产. 卜模拟过程的字符串为三 卜己生产* fit进程名Consumerk-继续氐退出模拟指令流程一逋成功辛梓舍酒费者檸拟, ”模拟过程的字符甬知.abedef *己注产 :飜 森程名Producer:s«i进蘇制块的信Run息一 等符谊因Hull numei*R

25、eadvNullL 继续0-退出.二一一帳拟指令流程一*就绪进程车数为沱*闿睾命生产进粪木数为洱 -生产無肖费者模拟 卜模拟过程的字符串为:ahedef 卜已生产 F空缓奁 r己消蟻陞程名Producer进秦善制块的勺Keadi/言息*一 等待原因 NullonsunepBlockS2也继续0退出博拟指令流程一 术数为吃JlSw模拟abedef进赛善制块的信自Run等待蔗因NullReadsr Null断点断点断点1樓拟指令流程一 *就绪进程不数为次* R字符成功入驻空缓存?生产者消费者険拟*模拟过程的字符串为:abedef *己坐产F*己嚅蘇惟程名IProdueer逬廳制块的信自Run等待備因Null断点3ConsumerBlockS2h继续0退岀愎拟指令流程一*就统进程个数为迢 *生产iftfegoto 0操作*剩余字符count=5个 生产者消费者模拟 *模拟过程的字符串为:abedef *己生产2 *空缘在* *己消蛊进程名Producer逬程控制块的信皀状态Run口殛 等待原因Null断点0Consuner1 继续0退岀ReadyNull进程名Produce!*自 等待原因 Null进廳制块瞬Stop断点-1ReadyNull二樓禅指令流程一呈goto 0操作 count=0个 東生产?生古者消费者模拟 模拟过程的字符串为:abcdef 己生产:abcdef 继续0退岀

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1