寝室长de
#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為s2int 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為S2printf("【提示】等待原因為: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() //初始化各參數
{//namechar 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");elseprintf("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");elseprintf("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(); //循環執行調度器}
}
總結
- 上一篇: 使用 Access SQL 插入、更新和
- 下一篇: PTA L2-016 愿天下有情人都是失