C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx

上传人:b****5 文档编号:18900385 上传时间:2023-01-02 格式:DOCX 页数:13 大小:117.73KB
下载 相关 举报
C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx_第1页
第1页 / 共13页
C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx_第2页
第2页 / 共13页
C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx_第3页
第3页 / 共13页
C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx_第4页
第4页 / 共13页
C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx

《C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx(13页珍藏版)》请在冰豆网上搜索。

C语言编程模拟生产者和消费者问题附代码程序Word格式文档下载.docx

在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。

(2)生产者一一消费者问题。

假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。

消费者每次从缓冲器内取出一件产品去消费。

禁止生产者将产品放入已满的缓冲器内,禁止消费者从空缓冲器内以产品。

假定缓冲器内可同时存放10件产品。

那么,用PV操作来实现生产者和消费者之间的同步,生产者和消费者两个进程的程序如下:

B:

arraP[0..9]ofproducts;

s1,s2;

semaphore;

s1:

=10,s2:

=0;

IN,out:

integer;

IN:

out:

cobegin

procedureproducer;

c:

products;

begin

L1:

Produce(c);

P(s1);

B[IN]:

=C;

=(IN+1)mod10;

V(s2);

gotoL1

end;

procedureconsumer;

G:

L2:

p(s2);

=B[out];

=(out+1)mod10;

v(s1);

consume(G);

gotoL2

coend.

其中的semaphore和products是预先定义的两个类型,在模拟实现中semaphore用integer代替,products可用integer或char等代替。

(3)进程控制块PCB。

为了记录进程执行时的情况,以及进程让出处理器后的状态,断点等信息,每个进程都有一个进程控制块PCB。

在模拟实习中,假设进程控制块的结构如

图3-1。

其中进程的状态有:

运行态、就绪态、等待态和完成态。

当进程处于等待态时,在进程控制块PCB中要说明进程等待原因(在模拟实习中进程等待原因是为等待信号量s1或S2);

当进程处于等待态或就绪态时,PCB中保留了断点信息,一旦进程再度占有处理器则就从断点位置继续运行;

当进程处于完成状

态,表示进程执行结束。

程名|

状态等待原因

|断点图3-1进程控制块结构

(4)处理器的模拟。

计算机硬件提供了一组机器指令,处理器的主要职责是解释执行机器指令。

为了模拟生产者和消费者进程的并发执行,我们必须模拟一组指令和处理职能。

模拟的一组指令见图3-2,其中每条指令的功能由一个过程来实现。

用变量PC来模拟“指令计数器”,假设模拟的指令长度为1,每执行一条模拟指令后,PC加1,提出下一条指令地址。

使用模拟的指令,可把生产者和消费者进程的程序表示为图3-3的形式。

定义两个一维数组PA[0..4]和SA[0..4],每一个PA[i]存放生产者程序中的一条模拟指令执行的入口地址;

每个SA[i]存放消费者程序中的一条模拟指令执行

的入口地址。

于是模拟处理器执行一条指令的过程为:

取出PC之值,按PA[PC]

或SA[PC]得模拟指令执行的入口地址,将PC之值加1,转向由入口地址确定的相应的过程执行。

功能

模拟的指令

p(s)

执行P操作原语

v(s)

执行V操作原语

put

=product;

=(IN+1)mod10

GET

=(out+1)mod10

produce

输入一个字符放入C中

consume

打印或显示G中的字符

GOTOL

PC:

=L

NOP

空操作

图3-2模拟的处理器指令

 

序号

生产者程序

消费者程序

p(S2)

1

PP(S1)

2

PUT

V(S1)

3

V(S2)

4

gotoO

goto0

图3-3生产者和消费者程丿

(5)程序设计

本实习中的程序由三部分组成:

初始化程序、处理器调度程序、模拟处理器指令执行程序。

各部分程序的功能及相互间的关系由图3-4至图3-7指出。

箝现行进程■为生产

taa.pcf=t>

图3-4初始化流程

保护理输FC-*号前迸程P亡R的斷点:

械机选擇--就缔竝程曲为理行避程

料观行进麗找告改

为运狞姦

现疗*秤忙E的■MAJK^pc

帳ft!

处思阵柑令枫行锂序

图3-5模拟处理器调度

•初始化程序:

模拟实习的程序从初始化程序入口启动,初始化工作包括对信号量si、s2赋初值,对生产者、消费者进程的PCB初始化。

初始化后转向处理调度程序,其流程如图3-4。

•处理器调度程序:

在计算机系统中,进程并发执行时,任一进程占用处理

器执行完一条指令后就有可能被打断而让出处理器由其它进程运行。

故在模拟系

统中也类似处理,每当执行一条模拟的指令后,保护当前进程的现场,让它成为

非运行态,由处理器调度程序按随机数再选择一个就绪进程占用处理器运行。

理器调度程序流程见图3-5。

建祁为生产

*

p<

?

i=*+i

拖』转问軒摸拟‘垢爭对雀的n穆

JIIT丄IL

sjjGoTC

UIGET||produce卜口皿注咋!

!

VCa>

F

.il.1.i

i

覽现轩进程为就箱态

返U1

TIZ

图3-6模拟处理器指令执行

⑻模拟P(s)(b)模拟V(s)

图3-7模拟PV操作的执行

且PC加1指向下一条指令。

模拟处理器指令执行程序的流程图见图3-6和图3-7

另外,为了使得模拟程序有一个结束条件,在图3-6中附加了“生产者运行结束”的条件判断,模拟时可以采用人工选择的方法实现。

图3-7给出了P(s)

和V(s)模拟指令执行过程的流程。

其它模拟指令的执行过程已在图3-2中指

附录:

代码

#include<

stdio.h>

stdlib.h>

conio.h>

windows.h>

#defineNULLO

structspcb

{

charname;

charstate;

charwhP;

intdd;

};

tPpedefstructspcbpcb;

pcbproducter,consumer,Gprocess,Gprocess1;

ints1,s2,i,j,in,out,pc,m;

chararraP[10];

charc,G;

intpa[6],sa[6];

intp(ints)/Gp操作原语G/

s=s-1;

if(s<

0)

process->

state='

B'

;

/GB表示阻塞GIprocess_>

whP='

s:

}

else

W;

/GW表示就绪G/

return(s);

intv(ints)/Gv操作原语G/

s=s+1;

=0)

{process1->

state=W;

return(s);

charRanChar()

chararr[10]={'

a'

'

b'

c'

d'

e'

f,'

g'

h'

i'

j'

returnarr[abs(rand()%10)];

voidput()

//printf("

\npleaseproductanPchar!

"

);

//scanf("

\n%c"

&

c);

Sleep(1000);

arraP[in]=RanChar();

in=(in+1)%10;

printf("

productacharis%c!

\n"

arraP[in-1]);

intk=0;

for(m=0;

m<

10;

m++)

{if(arraP[m]!

="

){printf("

%c"

arraP[m]);

k=k+1;

}一

printf("

缓冲池中有%d个产品\n"

k);

voidget()

G=arraP[out];

\n%cgetacharfronbuffer"

G);

arraP[out]="

out=(out+1)%10;

intk=0;

voidgotol()

pc=0;

voidnop()

{;

voiddisp()/G建立进程显示函数,用于显示当前进程G/

\nname\tstate\twhP\tdd\n"

|%c\t"

process->

name);

state);

whP);

|%d\t"

dd);

voidinit()/G初始化程序G/

s1=10;

/Gs1表示空缓冲区的数量G/

s2=0;

/Gs2表示满缓冲区的数量G/producter.name='

p'

/G对生产者进程初始化G/

producter.state=W;

producter.whP="

producter.dd=0;

consumer.name='

/G对消费者进程初始化G/

consumer.state=W;

consumer.whP="

consumer.dd=0;

for(intk=O;

k<

1O;

k++)

arraP[k]="

}voidbornpa()/G将生产者程序装入pa[]中G/

for(i=0;

i<

=3;

i++)

pa[i]=i;

}voidbornsa()/G将消费者程序装入sa[]中G/

sa[i]=i;

voiddiaodu()/G处理器调度程序G/

while((producter.state=='

W)||(consumer.state==W)){

G=rand();

/GG随机获得一个数G/G=G%2;

/G对G取于G/

if(G==O)/G若G等于零,则执行生产者进程,反之执行消费者进程G/

process=&

producter;

/Gprocess表示现行进程,将现行进程置为生产者进程G/

process仁&

consumer;

process1=&

pc=process->

dd;

i=pc;

/G此时把PC的值付给IG/

if((process->

name=='

)&

&

(process_>

state==W))

j=pa[i];

pc=i+1;

switch(j)

case0:

s1=p(s1);

dd=pc;

break;

case1:

put();

case2:

s2=v(s2);

case3:

gotol();

elseif((process->

name=='

(process->

state=='

W))/G执行消费者进程且该进程处

于就绪状态G/

j=sa[i];

caseO:

s2=p(s2);

/G申请资源,若没有申请到则跳转G/case1:

get();

case2:

s1=v(s1);

case3:

}/GendelseG/

}/GendwhileG/printf("

\nTheprogramisover!

voidmain()

init();

bornpa();

bornsa();

diaodu();

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

当前位置:首页 > 农林牧渔 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1