前言
参考代码
声名:主要根据这篇文章的思路,在其基础上增加了信号量机制。
题目
有一个盘子,可以放5个水果(苹果or桔子)。父亲每次向盘子随机放入一个水果(苹果 or桔子)父亲放入水果的次数不少于11次。儿子只吃桔子,女儿只吃苹果。请编程使用信号量机制模拟解决此进程同步问题。打印信息包括盘子的情况、调度的情况以及父亲、儿子或者女儿执行的操作。
题目解析
有题目可以得知父亲是生产者,儿子与女儿是消费者,其中,父亲随机在盘子中放入苹果和桔子,盘子满无法放入,当女儿和儿子那水果时,需要注意的是,两者只针对置于顶层的盘子所盛的水果是否是他们想要的,举例来说,现在第一个盘子里有苹果,第二个盘子里有桔子,而第一个盘子在顶层(即消费者指针指向第一个盘子)时,儿子去拿水果,会显示没有桔子,尽管桔子就在第二个盘子。
代码解释
- 定义消费者/生产者结构体存放父亲、女儿、儿子信息
- 定义盘子结构体
- 初始化消费者、生产者
- 将五个盘子初始化为循环链表
- 父亲用put指针操作盘子,儿子,女儿共用take指针操作盘子
- 同步信号量WAIT
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>
#define PLATES 5
int WAIT[3] = {0, 0, 0};
struct Pcb{
char name[20];
int pid;
int style;
int fruit;
char *act;
};
struct PcbList{
struct Pcb item;
struct Pcb * next;
};
struct Pan{
char a[3];
int frt;
struct Pan * next;
};
struct PcbList * waitQueue;
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);
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");
}
void wait(struct PcbList * head, struct Pcb * process){
struct PcbList * temp = head;
while(temp->next!=NULL){
temp = temp->next;
}
int pid = (*process).pid;
WAIT[pid] = 1;
temp->next = process;
temp = temp->next;
temp->next = NULL;
return;
};
struct Pcb * wakeUp(struct PcbList * head, struct Pcb * process){
struct PcbList * temp = head;
struct PcbList * pre = NULL;
while(temp!=NULL){
if(temp->item.pid == process->pid){
int pid = (*process).pid;
WAIT[pid] = 0;
pre->next = temp->next;
return &(temp->item);
}else{
pre = temp;
temp = temp->next;
}
}
return NULL;
};
struct Pcb * PutFruit(struct Pan * put,struct Pcb * dad, struct Pcb * son, struct Pcb * dau){
if(put->frt != 2){
dad->act = "father: Pans is full, block me";
wait(waitQueue, dad);
}
else{
if(rand()%2==0){
put->frt = 0;
put = put->next;
dad->act = wakeUp(waitQueue, son) == NULL? "father: put an 'O'range": "father: put an 'O'range\nson wakeup";
}
else{
put->frt = 1;
put = put->next;
dad->act = wakeUp(waitQueue, dau) == NULL? "father: put an 'A'pple": "father: put an 'A'pple\ndau wakeup";
}
}
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, block me";
wait(waitQueue, son);
}
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, block me";
wait(waitQueue, dau);
}
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;
waitQueue = (struct PcbList *)malloc(sizeof(struct PcbList));
waitQueue->next = NULL;
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 && WAIT[flag] == 0 ){
put = PutFruit(put,&Dad, &Son, &Dau);
Output(&Dad,head);
}
else if(flag == 1 && WAIT[flag] == 0){
take = GetOrange(take, &Son);
Output(&Son,head);
Son.style = 1;
}
else if(flag == 2 && WAIT[flag] == 0){
take = GetApple(take, &Dau);
Output(&Dau,head);
Son.style = 1;
}else{
num++;
continue;
}
}
return 0;
}