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

上传人:聆听****声音 文档编号:2001404 上传时间:2023-05-02 格式:DOC 页数:16 大小:287KB
下载 相关 举报
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第1页
第1页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第2页
第2页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第3页
第3页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第4页
第4页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第5页
第5页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第6页
第6页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第7页
第7页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第8页
第8页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第9页
第9页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第10页
第10页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第11页
第11页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第12页
第12页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第13页
第13页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第14页
第14页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第15页
第15页 / 共16页
模拟PV操作同步机构-且用PV操作解决生产者——消费者问题.doc_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

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

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

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

实验四:

同步机构实验报告

学院:

专业班级:

姓名:

学号:

一、实验内容:

模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。

二、实验目的:

进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。

我们把若干个进程都能进行访问和修改的那些变量称为公共变量。

由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。

为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。

一般说,同步机构是由若干条原语——同步原语——所组成。

本实验要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。

三、实验题目:

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

四、此次用到的数据结构知识如下:

typedefstructPcb{

charname[10];//进程名

charstate[10];//运行状态

charreason[10];//若阻塞,其原因

intbreakp;//断点保护

structPcb*next;//阻塞时的顺序

进程名

状态

等待原因

断点

后继进程

}Pcb,*link;

进程控制块结构

定义两个进程:

linkp1;//生产者进程,linkc1;//消费者进程。

pc程序计数器和

linkready;就绪队列,linkb_s1;s1阻塞队列,linkb_s2;s2阻塞队列。

五、实验源代码:

分为四个头文件。

1、a.h头文件代码如下:

#include

#include

#include/*malloc()等*/

#include/*INT_MAX等*/

#include/*EOF(=^Z或F6),NULL*/

#include/*atoi()*/

#include/*eof()*/

#include/*floor(),ceil(),abs()*/

#include/*exit()*/

#include

usingnamespacestd;

#include

#defineBUF10//缓存的大小

#defineMAX20//最大可以输入的字符

2、b.h头文件代码如下:

//数据结构的定义和全局变量

typedefstructPcb{

charname[10];//进程名

charstate[10];//运行状态

charreason[10];//若阻塞,其原因

intbreakp;//断点保护

structPcb*next;//阻塞时的顺序

}Pcb,*link;

ints1,s2;//信号量

linkp1;//生产者进程

linkc1;//消费者进程

charstr[MAX];//输入的字符串

charbuffer[BUF];//缓冲池

intlen;//输入长度

intsp=0;//string的指针

intin=0;//生产者指针

intout=0;//消费者指针

chartemp;//供打印的临时产品

charrec_p[MAX];//生产记录

intrp1=0;//生产记录指针

charrec_c[MAX];//消费记录

intrp2=0;//消费记录指针

linkready;//就绪队列

linkb_s1;//s1阻塞队列

linkb_s2;//s2阻塞队列

intpc;//程序计数器

intcount;//字符计数器

intcon_cnt;//消费计数器

3、c.h头文件代码如下:

voidinit();//初始化

voidp(ints);//P操作

voidv(ints);//V操作

voidblock(ints);//阻塞函数

voidwakeup(ints);//唤醒函数

voidcontrol();//处理机调度

voidprocessor();//处理机执行

voidprint();//打印函数

voidinit(){//初始化

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));//建立新的结点,并初始化为消费者

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;//阻塞进程为NULL

pc=0;

con_cnt=0;//消费计数器

}

voidp(ints){

if(s==1){//p(s1)

s1--;

if(s1<0)

block

(1);//阻塞当前生产进程

else{

printf("\t*s1信号申请成功!

\n");

ready->breakp=pc;//保存断点

}

}

else{//p(s2)

s2--;

if(s2<0)

block

(2);//阻塞当前消费进程

else{

printf("\t*s2信号申请成功!

\n");

ready->breakp=pc;//保存断点

}

}

}

voidv(ints){

if(s==1){//v(s1)

s1++;

if(s1<=0)

wakeup

(1);//唤醒生产进程

ready->breakp=pc;//保存断点

}

else{//v(s2)

s2++;

if(s2<=0)

wakeup

(2);//唤醒消费进程

ready->breakp=pc;//保存断点

}

}

voidblock(ints){//阻塞函数的定义

linkp;

intnum1=0;

intnum2=0;

if(s==1){//生产进程

strcpy(p1->state,"Block");//改变状态

strcpy(p1->reason,"S1");//说明原因

p=b_s1;

while(p){

num1++;

p=p->next;//p的值为NULL,表示队尾

}

if(!

b_s1)

b_s1=p1;

else

p=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=c1;

else

p=c1;

ready->breakp=pc;//保存断点

ready=ready->next;//在就绪队列中去掉,指向下一个

c1->next=NULL;

printf("\t*c1消费进程阻塞了!

\n");

num2++;

}

printf("\t*阻塞的生产进程个数为:

%d\n",num1);

printf("\t*阻塞的消费进程个数为:

%d\n",num2);

}

voidwakeup(ints){//唤醒函数的定义

linkp;

linkq=ready;

if(s==1){//唤醒b_s1队首进程,生产进程队列

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,"Ready");

strcpy(p->reason,"Null");

while(q->next)//插入就绪队列

q=q->next;

q->next=p;

p->next=NULL;

printf("\t*c1消费进程唤醒了!

\n");

}

}

voidcontrol()//处理器调度程序

{

intrd;

intnum=0;

linkp=ready;

if(ready==NULL)//若无就绪进程,结束

return;

while(p)//统计就绪进程个数

{

num++;

p=p->next;//最终p变为NULL

}

printf("\t*就绪进程个数为:

%d\n",num);

time_tt;

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");

}

else

strcpy(ready->state,"Run");

pc=ready->breakp;

}

voidprocessor(){//模拟处理器指令执行

if(strcmp(ready->name,"Producer")==0)//当前进程为生产者

switch(pc)

{

case0:

//produce

printf("\t*生产者生产了字符%c\n",str[sp]);

rec_p[rp1]=str[sp];//添加到生产记录

sp=(sp+1)%len;

pc++;

ready->breakp=pc;//保存断点

break;

case1:

//p(s1)

pc++;

p

(1);

break;

case2:

//put

buffer[in]=rec_p[rp1];//放到缓冲区

printf("\t*%c字符成功入驻空缓存!

\n",buffer[in]);

rp1++;

in=(in+1)%BUF;

pc++;

ready->breakp=pc;//保存断点

break;

case3:

//v(s2)

pc++;

printf("\t*释放一个s2信号\n");

v

(2);

break;

case4:

//goto01

printf("\t*生产进程goto0操作\n");

pc=0;

count--;//剩余字符个数减1

printf("\t*剩余字符count=%d个\n",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)

{

case0:

//p(s2)

pc++;

p

(2);

break;

case1:

//get

printf("\t*消费者取字符!

\n");

temp=buffer[out];

out=(out+1)%BUF;

pc++;

ready->breakp=pc;//保存断点

break;

case2:

//v(s1)

pc++;

printf("\t*释放一个s1\n");

v

(1);

break;

case3:

//consume

printf("\t*消费了字符%c\n",temp);

rec_c[rp2]=temp;//添加到消费记录

rp2++;

con_cnt++;

if(con_cnt>=len){

strcpy(c1->state,"Stop");//完成态

c1->breakp=-1;

return;

}

pc++;

ready->breakp=pc;//保存断点

break;

case4:

//goto0

printf("\t*消费进程goto0操作\n");

pc=0;

ready->breakp=pc;//保存断点

}

}

voidprint(){

inti,j;

printf("————————生产者消费者模拟———————\n");

printf("*模拟过程的字符串为:

\t");

printf("%s\n",&str);

printf("*已生产:

");

for(j=0;j<=rp1;j++)

printf("%c",rec_p[j]);

printf("\n*空缓存:

");

for(j=rp2;j<=rp1;j++)

printf("%c",buffer[j]);

printf("\n*已消费:

");

for(j=0;j<=rp2;j++)

printf("%c",rec_c[j]);

printf("\n———————进程控制块的信息————————\n");

printf("进程名\t\t状态\t等待原因\t断点\n");

printf("%s\t%s\t%s\t\t%d\n\n",p1->name,p1->state,p1->reason,p1->breakp);

printf("%s\t%s\t%s\t\t%d\n",c1->name,c1->state,c1->reason,c1->breakp);

printf("———————————————————————\n");

printf("1.继续0.退出\n");

scanf("%d",&i);

if(i==0){

exit(0);

}

}

4、main头文件代码如下:

#include"a.h"

#include"b.h"

#include"c.h"

voidmain(){

printf("*生产者消费者模拟\n");

printf("—————————\n");

printf("*请输入字符串:

\n");

scanf("%s",str);//string数组存放将要产生的字符

len=strlen(str);

count=len;//输入字符的个数

init();//初始化

while(con_cnt

{

system("cls");//清屏操作

printf("—————————模拟指令流程————————\n");

control();//处理器调度程序

processor();//模拟处理器指令执行

print();//输出显示各个信息

}

printf("\n程序结束!

\n");

}

六、运行结果截图:

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

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2