问题描述
模拟:父亲随机地剥橘子,削苹果,剥橘子要快些,削苹果要慢些,完成后放在盘子里,盘子只能容纳3颗水果。儿子只吃苹果,女儿吃橘子,儿子吃得快,女儿吃得慢。(假设他们都吃不饱)
使用信号量机制,并用三个进程模拟父亲、儿子、女儿的动作。
代码
i_semop.h
#ifndef I_SEMOP_H
#define I_SEMOP_H
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>//fundamental types of data
#include<sys/ipc.h>//interprocess communication
#include<sys/sem.h>//semaphore opration
#include<errno.h>
#include<fcntl.h>//file control
/*函数声明*/
/*信号量管理函数*/
int CreatSem(int value);
int SetSemValue(int sem_id, int value);
int DeleteSem(int sem_id);
/*P、V原语*/
int Psem(int sem_id);
int Vsem(int sem_id);
int rand_num();
#endif
i_semop.c
#include"i_semop.h"
int SetSemValue(int sem_id, int value)
{
if(semctl(sem_id, 0, SETVAL, value) == -1)
return -1;
return 1;
}
int CreatSem(int value)
{
int sem_id;
sem_id = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
if(-1 == sem_id)
return -1;
if(SetSemValue(sem_id, value) == -1)
return -1;
return sem_id;
}
int DeleteSem(int sem_id)
{
if(semctl(sem_id, 0, IPC_RMID) == -1)
return -1;
return 1;
}
int Psem(int sem_id)
{
struct sembuf semb;
semb.sem_num = 0;
semb.sem_op = -1;
semb.sem_flg = SEM_UNDO;
if (-1 == semop(sem_id, &semb, 1))
return -1;
return 1;
}
int Vsem(int sem_id)
{
struct sembuf semb;
semb.sem_num = 0;
semb.sem_op = 1;
semb.sem_flg = SEM_UNDO;
if (-1 == semop(sem_id, &semb, 1))
return -1;
return 1;
}
int rand_num()
{
int ap_or_or = 3;
/*获取一个随机数,0或者1, 表示随机的选苹果或者橘子*/
srand(time(NULL));/*设置随机种子*/
ap_or_or = rand() % 2;
return ap_or_or;
}
main.c
#include"i_semop.h"
#include<signal.h>
#include<time.h>
#define APPLE 0
#define ORANGE 1
/*定义信号量为全局变量*/
int plate_sem = 0;
int apsem_in_plate = 0;
int orsem_in_plate = 0;
int main()
{
/*信号量初始化*/
plate_sem = CreatSem(3);
if(-1 == plate_sem)
fprintf(stderr, "creat plateSem failed\n");
apsem_in_plate = CreatSem(0);
if(-1 == plate_sem)
fprintf(stderr, "creat apsem_in_plate failed\n");
orsem_in_plate = CreatSem(0);
if(-1 == plate_sem)
fprintf(stderr, "creat orsem_in_plate failed\n");
/*创建代表进程父亲,女儿,儿子*/
pid_t pid_array[3];
/*模拟动作*/
pid_t pid = fork();
if(0 == pid)//代表父亲
{
while(1)
{
int choice_apor = rand_num();//随机选择苹果或橘子
//printf("随机数是%d\n",choice_apor);
if(APPLE == choice_apor)//如果是削苹果皮
{
sleep(2);
Psem(plate_sem);
printf("父亲削了一个苹果\n");
Vsem(apsem_in_plate);
}
else //如果是剥橘子皮
{
sleep(1);
Psem(plate_sem);
printf("父亲剥了一个橘子\n");
Vsem(orsem_in_plate);
}
}
}
else
pid_array[0] = pid;
pid = fork();
if(0 == pid)//代表儿子
{
while(1)
{
Psem(apsem_in_plate);
printf("儿子吃了一个苹果\n");
Vsem(plate_sem);
sleep(1);
}
}
else
pid_array[1] = pid;
pid = fork();
if(0 == pid) //代表女儿
{
while(1)
{
Psem(orsem_in_plate);
printf("女儿吃了一个橘子\n");
Vsem(plate_sem);
sleep(2);
}
}
else
pid_array[2] = pid;
while(1)
{
char cmd = getchar();
if('q' == cmd)
break;
}
for(int i = 0; i < 3; i++)
kill(pid_array[i], SIGTERM);
DeleteSem(plate_sem);
DeleteSem(apsem_in_plate);
DeleteSem(orsem_in_plate);
return 0;
}