#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define Total 10 //生产/消费缓存区最大数量
#define Num 5 //表示一个进程的指令总数
struct PCB {
char name[20]; //进程名
char state; //进程状态 r:运行 R:就绪 W:等待 E:完成
int waitReason; //表示S1和S2 0为s1 1为s2
int point; //断点
}producer, consumer, *currentPC; //定义生产者,消费者PCB和指针
int s1, s2; //s1:当前资源可存量 s2:当前资源可取量
int PA[Num], PB[Num]; //分别表示两个进程的指令标号集
int PC; //指令计数器
int Buffer[Total] = {0}; //缓冲区
int Buflag = 0; //缓冲区指针
int OUTPUT = -999;
int S = 0; //存放产品
//P操作
void P(int s,int nq) //s为某类公共资源,类别可由nq来判断,s为对应实际操作数据
{
if (nq == 0)
{
s1--;
s = s1;
}
else
{
s2--;
s = s2;
}
if (s < 0) //无资源剩余
{
currentPC->state = 'W'; //状态为等待
currentPC->waitReason = nq; //等待原因 0为S1 1为S2
printf("【提示】等待原因为:S%d\n", currentPC->waitReason+1); //0对应S1 1对应S2 加一即可
}
else //有资源剩余
{
printf("【提示】无需等待\n");
currentPC->state = 'R'; //状态为就绪
}
}
void V(int s, int nq) //s为实际操作数 nq为标识符
{
if (nq == 0)
{
s1 = s1 + 1;
s = s1;
}
else
{
s2 = s2 + 1;
s = s2;
}
if (s <=0) //单生产者/消费者 阻塞值最小只有-1
{
if (producer.waitReason == nq)
{
producer.state = 'R';
producer.waitReason = -1;
printf("【提示】释放一个producer");
}
if (consumer.waitReason == nq)
{
consumer.state = 'R';
consumer.waitReason = -1;
printf("【提示】释放一个consumer");
}
}
else
{
printf("无进程释放");
currentPC->state = 'R';//将现有进程置为就绪态
}
}
void initial() //初始化各参数
{
//name
char Pname[10] = "producer";
char Cname[10] = "consumer";
int i = 0;
while (Pname[i] != '\0')
{
producer.name[i] = Pname[i];
i++;
}
i = 0;
while (Cname[i] != '\0')
{
consumer.name[i] = Cname[i];
i++;
}
//指令标识符数组初始化
for (i = 0; i < Num; i++)
{
PA[i] = i;
PB[i] = i;
}
//PC初始化
PC = 0;
//状态初始化
producer.state = 'R';
consumer.state = 'R';
//资源初始化
s1 = 10; s2 = 0;
//断点初始化
producer.point = 0;
consumer.point = 0;
//等待原因初始化
producer.waitReason = -1;
consumer.waitReason = -1;
}
void show_Buffer()
{
int i = 0;
for (i = 0; i < Total; i++)
{
printf("%d ", Buffer[i]);
}
}
void show_PCB(int flag)
{
//flag表示打印类型
if (flag == 0) //打印生产者PCB
{
printf("Name:");
puts(producer.name);
printf("State:%c\n", producer.state);
if (producer.waitReason == 0)
printf("Waitreason:S1\n");
else if (producer.waitReason == 1)
printf("Waitreason:S2\n");
else
printf("Waitreason:None\n");
printf("Point:%d\n\n", producer.point);
}
if (flag == 1) //打印消费者PCB
{
printf("Name:");
puts(consumer.name);
printf("State:%c\n", consumer.state);
if (consumer.waitReason == 0)
printf("Waitreason:S1\n");
else if (consumer.waitReason == 1)
printf("Waitreason:S2\n");
else
printf("Waitreason:None\n");
printf("Point:%d\n\n", consumer.point);
}
}
void produce(int s) //将临时产品暂时保存
{
S = s;
}
void Running() //模拟处理器执行
{
int q=0,j=-1,i=0; //q用来标识生产者or消费者 j用来标识switch函数入口函数标号 i用来过度PC值
i = PC; //保存PC值为i
//初始化入口函数下标
if (currentPC->name[0] == 'p') //选中生产者
{
j = PA[i];
q = 0; //标识符
}
if (currentPC->name[0] == 'c') //选中消费者
{
j = PB[i];
q = 1;
}
PC = i + 1;
//执行过程
//char S;//临时存放生产商品
int s=0;
switch (j)
{
case 0:
if (q == 0) //生产者执行【produce】
{
printf("【提示】请输入一件产品:");
scanf("%d", &s);//产品暂存到S中
produce(s);//暂存商品
}
else //消费者【P(S2)】
{
P(s2, 1); //1表示操作S2
}
break;
case 1:
if (q == 0) //生产者【P(s1)】
{
P(s1, 0);
}
else //消费者【GET】
{
printf("【提示】消费者取一个产品\n");
//consumerList[cflag] = producerList[cflag];//取商品
//cflag = (cflag + 1) % Total;//下标循环右移
OUTPUT = Buffer[Buflag - 1];
Buffer[Buflag - 1] = -1;
Buflag = (Buflag - 1) % Total;
currentPC->state = 'R'; //设置为就绪态
}
break;
case 2:
if (q == 0) //生产者【PUT】
{
printf("【提示】生产者产入一个商品");
//producerList[pflag] = S; //将产品存入生产者数组
Buffer[Buflag] = S;
//pflag = (pflag + 1) % Total;
Buflag = (Buflag + 1) % Total;
currentPC->state = 'R';//设置为就绪态
}
else //消费者【V(s1)】
{
V(s1, 0);
}
break;
case 3:
if (q == 0) //生产者【V(s2)】
{
V(s2, 1);
}
else //消费者【consume】--打印
{
printf("【提示】消费了一个产品:%d\n",OUTPUT);
}
break;
case 4:
if (q == 0) //生产者【goto 0】
{
PC = 0;
}
else //消费者【goto 0】
{
PC = 0;
}
break;
}
if (q==0&&j==4)//判断生产者进程是否运行结束
{
printf("【提示】生产者程序已执行完\n");
}
}
void Scheduling()//处理器调度程序--选择出执行阶段的currentPC
{
int select; //0为生产者 1为消费者
//手动选择模拟调度
while (producer.state == 'R' || consumer.state == 'R')
{
printf("【提示】请选择本次执行的程序(0为生产者,1为消费者)");
scanf("%d", &select);
while ((select == 0 && producer.state != 'R') || (select == 1 && consumer.state != 'R'))
{
if (select == 0)
{
printf("【提示】生产者进程被挂起,请重新选择:");
scanf("%d", &select);
}
else
{
printf("【提示】消费者进程被挂起,请重新选择:");
scanf("%d", &select);
}
}
if (select == 0)
{
if (producer.state == 'R')
{
currentPC = &producer;
}
else
{
printf("【提示】生产者进程被挂起,无法执行");
//currentPC = &consumer;
}
}
else
{
if (select == 1)
{
if (consumer.state == 'R')
{
currentPC = &consumer;
}
else
{
printf("【提示】消费者进程被挂起,无法执行");
//currentPC = &consumer;
}
}
}
//设置currentPC的参数
PC = currentPC->point;
Running();//执行进程
currentPC->point = PC;
//printf("\n当前PC值为:%d\n", PC);
printf("【提示】当前缓冲区为:");
show_Buffer();
printf("\n【提示】当前S1值为:%d 当前S2值为:%d\n\n", s1,s2);
show_PCB(0);
show_PCB(1);
printf("-----分割线-----\n");
}
}
void main() {
initial(); //初始化
while (1)
{
Scheduling(); //循环执行调度器
}
}
寝室长de
最新推荐文章于 2024-11-09 20:38:27 发布
该代码实现了一个生产者-消费者问题的模拟,使用了PCB(进程控制块)结构来管理进程状态。程序中定义了两个进程,生产者和消费者,分别通过P和V操作进行资源的申请和释放。在模拟过程中,处理器调度程序会根据进程状态选择执行的进程,并显示缓冲区、资源状态和进程状态。
摘要由CSDN通过智能技术生成