操作系统作业——进程互斥同步的模拟
题目
有一个盘子,可以放5个水果(苹果or桔子)。父亲每次向盘子随机放入一个水果(苹果or桔子),父亲放入水果的次数不少于11次。儿子只吃桔子,女儿只吃苹果。请编程使用信号量机制模拟解决此进程同步问题。打印信息包括盘子的情况、调度的情况以及父亲、儿子或者女儿执行的操作。
题目解析
有题目可以得知父亲是生产者,儿子与女儿是消费者,其中,父亲随机在盘子中放入苹果和桔子,盘子满无法放入,当女儿和儿子那水果时,需要注意的是,两者只针对置于顶层的盘子所盛的水果是否是他们想要的,举例来说,现在第一个盘子里有苹果,第二个盘子里有桔子,而第一个盘子在顶层(即消费者指针指向第一个盘子)时,儿子去拿水果,会显示没有桔子,尽管桔子就在第二个盘子。
代码解释
1. 定义消费者/生产者结构体存放父亲、女儿、儿子信息
2. 定义盘子结构体
3. 初始化消费者、生产者
4. 将五个盘子初始化为循环链表
5. 父亲用put指针操作盘子,儿子,女儿共用take指针操作盘子
代码实现
#include <stdio.h>
#include <time.h>
#include <malloc.h>
#define PLATES 5
struct Pcb{ //储存父亲,儿子,女儿信息的结构体
char name[20]; //名称
int Pid; //消费者/生产者id
int style; //决定工作方式,消费者还是生产者
int fruit; //决定生产或者消费何种水果
char *act;
};
struct Pan{ //盘子结构体
char a[3]; //字符数组分别代表桔子和苹果
int frt;
struct Pan * next; //指针
};
/*初始化盘子列表*/
void PanInit(struct Pan * head, int num){
int i; //循环辅助操作
struct Pan * np;//链表辅助操作指针
struct Pan * lp;
lp = head;
for(i=0;i<num;++i){
np = (struct Pan *)malloc(sizeof(struct Pan));
np->a[0] = 'O';
np->a[1] = 'A';
np->a[2] = ' ';
np->frt = 2;
lp->next = np;
np->next = NULL;
lp = np;
}
np->next = head->next; //构成循环链表
}
/*输出操作*/
void Output(struct Pcb *p,struct Pan * head){
int ps;
struct Pan * temp = head ->next; //输出盘子指针
printf("sched: %s \n",p->name); //输出操作人员name
printf("%s\n",p->act); //输出操作内容
if(p->style == 0){ //按要求输出盘子
printf("plate : |");
for(ps=0;ps<PLATES;++ps){
printf("%c|",temp->a[temp->frt]);
temp = temp->next;
}
printf("\n");
}
printf("\n");
}
/*父亲放水果操作*/
struct Pcb * PutFruit(struct Pan * put,struct Pcb * dad){
if(put->frt != 2){
//盘子满了
dad->act = "father: Pans is full";
}
else{
if(rand()%2==0){
put->frt = 0; //放水果操作
put = put->next;
dad->act = "father: put an 'O'range";
}
else{
put->frt = 1; //放苹果
put = put->next; //生产者指针后移
dad->act = "father: put an 'A'pple";
}
}
return put;
}
/*儿子吃桔子操作*/
struct Pcb * GetOrange(struct Pan * take,struct Pcb * son){
if(take->frt == 0){
take ->frt = 2;
son->style = 0;
take = take->next; //消费者指针后移
son->act = "son: eat an orange";
}
else{
son->act = "son: not orange";
}
return take;
}
/*女儿吃苹果操作*/
struct Pcb * GetApple(struct Pan * take,struct Pcb * dau){
if(take->frt == 1){
take ->frt = 2;
dau->style = 0;
take = take->next; //消费者指针后移
dau->act = "daughter: eat an apple";
}
else{
dau->act = "daughter: not apple";
}
return take;
}
int main(){
int num; //转换次数
int flag; //储存切换信号
struct Pcb Dad = {"father",0,0,0,NULL};
struct Pcb Son = {"son", 1, 1, 0, NULL};
struct Pcb Dau = {"daughter", 2, 1, 1, NULL};
struct Pan *head;
struct Pan *put;
struct Pan *take;
head = (struct Pan *)malloc(sizeof(struct Pan));
head->next = NULL;
PanInit(head,5);
put = head->next; //初始化果盘操作指针
take = head->next;
printf("Please input scheduling count:");
scanf("%d",&num);
srand((unsigned) time(NULL)); //产生种子用于随机调度
while(num--){
flag = rand()%3;
if(flag == 0){
put = PutFruit(put,&Dad); //生产者操作
Output(&Dad,head); //输出
}
else if(flag == 1){
take = GetOrange(take, &Son); //消费者操作
Output(&Son,head); //输出
Son.style = 1; //是否消费标记位重置
}
else if(flag == 2){
take = GetApple(take, &Dau);
Output(&Dau,head);
Son.style = 1;
}
}
return 0;
}