实验四同步机构.docx
《实验四同步机构.docx》由会员分享,可在线阅读,更多相关《实验四同步机构.docx(11页珍藏版)》请在冰点文库上搜索。
实验四同步机构
实验四--同步机构
实验四同步机构
一.实验内容
模拟实现用同步机构避免并发进程执行时可能出现的与时间有关的错误。
二.实验目的
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后,所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实验要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
三.实验题目
模拟PV操作同步机构,且用PV操作解决生产者——消费者的问题。
四.实验步骤
(1)程序中使用的数据结构及符号说明
structPCB//进程控制块
{
charp_name[23];
intm;//0:
运行,1:
就绪,2:
等待,3:
完成;
intwaitreason;//0:
信号S1,1:
信号S2;
intinteruptpoint;//设置断点
};
constintnum=5;
constintsales=10;
structPCB;//进程控制块
voidce();
voidp(int&s,intp,PCB*d);//P操作
voidv(int&s,intp,PCB*d);//V操作
(2)流程图
程序总体结构框图:
开始
初始化
运行
结束
初始化:
初始化信号量S1,S2(S1=10,S2=0),对生产者、消费者进程的PCB初始化。
初始化流程图:
运行部分框图:
开始
初始化指针
打印进程信息
进程队列为Y
空,
N
选择当前进程结束
运行时间加1
Y当前进程运
行完毕,
打印进程信息
N
打印进程信息删除当前进程
调整指针调整指针
(3)源代码(附注释)
//#include"stdafx.h"#include
#include
#include
usingnamespacestd;constintnum=5;
constintsales=10;
structPCB;//进程控制块
voidce();
voidp(int&s,intp,PCB*d);//P操作
voidv(int&s,intp,PCB*d);//V操作
/*int_tmain(intargc,_TCHAR*argv[])
{
return0;
}*/
structPCB//进程控制块
{
charp_name[23];
intm;//0:
运行,1:
就绪,2:
等待,3:
完成;
intwaitreason;//0:
信号S1,1:
信号S2;
intinteruptpoint;//设置断点
};
intproduce(int&C,intc)//生产产品c
{
C=c;
returnC;
}
ints1,s2,pa[num],sa[num],pc;PCBproducer,customer,*currp;voidinitial()//初始化程序
{
strcpy_s(producer.p_name,"producer");
producer.m=1;//初始化生产者为就绪状态
producer.interuptpoint=0;
strcpy_s(customer.p_name,"customer");
customer.m=1;//初始化消费者为就绪状态
customer.interuptpoint=0;
currp=&producer;
s1=10;
s2=0;
for(inti=0;i{
pa[i]=i;
sa[i]=pa[i];
}
pc=0;
}
voidcpuwork()
{
currp->interuptpoint=pc;//令当前执行指令送到断点中
intn;
while(producer.m==1||customer.m==1)//判断当前执行是生产者,还是消费者
{
cout<<"选择生产者进程或消费者进程(0表示生产者,1表示消费者):
";
cin>>n;
if(n==0)//0为表示生产者
{
if(producer.m==1)
currp=&producer;
else//否则消费者为就绪状态,执行消费者进程
{
cout<<"进程producer被挂起,无法执行,执行进程customer"<currp=&customer;
}
}else
if(n==1)//1为表示消费者
if(customer.m==1)
currp=&customer;
else//否则生产者为就绪状态,执行消费者进程
{
cout<<"进程customer被挂起,无法执行,执行进程producer"<currp=&producer;
}
currp->m=0;//令当前进程处于执行状态
pc=currp->interuptpoint;
ce();//执行
currp->interuptpoint=pc;
}
}
voidce()
{
inti,j,q,pt,xx,ss,nq,shangpin[sales],xiaofei[sales];
intC;
charw;xx=0;
ss=0;
nq=0
i=pc
if(strcmp(currp->p_name,"producer")==0)//pa[i]存放生产者程序中的一条模拟指令执行的
入口地址
{
j=pa[i];
q=0;
}
else//sa[i]存放消费者程序中的一条模拟指令执行的入口地址
{
j=sa[i];
q=1;
}
pc=i+1;
switch(j)//j表示当前程序中的一条模拟指令执行的入口地址
{
case0:
if(q==0)//输入一个字符放入中
{
cout<<"请生产一件产品(即输入一个数字):
";
cin>>pt;
produce(C,pt);
//pp=pt;
currp->m=1;
cout<<"产品已经生产";
}
else//执行消费者的P操作
{
nq=2;
p(s2,nq,currp);
}
break;
case1:
if(q==0)//执行生产者的P操作
{
nq=1;
p(s1,nq,currp);
}
else//执行消费者的取商品操作,X:
B[out];out:
=(out+1)mod10
{
cout<<"取一个产品";
xiaofei[xx]=shangpin[ss];
xx=(xx+1)%sales;
currp->m=1;
}
break;
case2:
if(q==0)//执行生产者的产品上架操作,B[IN]:
produce;IN:
=(IN+1)mod10
{
cout<<"有一个产品上架";
shangpin[ss]=produce(C,pt);
ss=(ss+1)%sales;
currp->m=1;
}
else//执行消费者的V操作
{
nq=1;
v(s1,nq,currp);
}
break;
case3:
if(q==0)//执行生产者的V操作
{
nq=2;
v(s2,nq,currp);
}
else//执行消费者的consume操作,打印或显示X中的字符
{
cout<<"消费了一个产品";
cout<currp->m=1;
}
break;
case4:
//返回到L0指令执行
currp->m=1;
break;
default:
;
}
cout<cout<<"生产者运行是否结束(Y/y,N/n):
";//判断生产者运行是否结束
cin>>w;
cout<if(w=='y'||w=='Y')
producer.m=3;}
voidp(int&s,intp,PCB*d)//P操作
{
s=s-1;
cout<<"测试信号量s"<
if(s<0)
{
d->m=2;
d->waitreason=p;
cout<p_name<<"进入等待~";
}
else
{
cout<p_name<<"无需等待。
";
d->m=1;
}
}
voidv(int&s,intp,PCB*d)//V操作
{
s=s+1;
if(s<=0)
{
if(producer.waitreason==p)
producer.m=1;
elseif(customer.waitreason==p)
customer.m=1;
if(strcmp(currp->p_name,"producer")==0)
cout<<"释放进程customer";
else
cout<<"释放进程producer";
}
else
{
cout<<"无进程释放~";
d->m=1;
}
}
voidmain()
{
initial();
cpuwork();
}
五.实验小结
通过用PV操作解决生产者——消费者问题的设计,使我更加
深刻的了解了PV操作的过程。
当进程处于等待态时,在进程控制块
PCB中要说明进程等待的原因;当进程处于等待态或就绪态时,PCB
中保留了断点信息,一旦进程再度占有处理器,则就从断点位置继续运行;当进程处于完结状态,表示进程执行结束。
在这次实验中,巩固了C语言编程知识,并且对用同步机构避免并发进程执行时可能出现的与时间有关的错误,及对PV操作的状况有了更形象的认识。