问题描述
抽烟者问题。假设一个系统中有三个抽烟者进程,每个抽烟者不断地卷烟并抽
烟。抽烟者卷起并抽掉一颗烟需要有三种材料:烟草、纸和胶水。一个抽烟者有烟
草,一个有纸,另一个有胶水。系统中还有两个供应者进程,它们无限地供应所有
三种材料,但每次仅轮流提供三种材料中的两种。得到缺失的两种材料的抽烟者在
卷起并抽掉一颗烟后会发信号通知供应者,让它继续提供另外的两种材料。这一过
程重复进行。
问题分析
1.考虑到:有可能会涉及到材料数修改的问题,所以2供应者3吸烟者全部互斥,暴力,就不会出任何问题。
2.对轮流的理解有两种,一种是只需一个供应者就可以满足吸烟要求,另外一种是两个配合。
3.供应者准备好以后就给吸烟者发信号,吸烟者吸完给供应者发信号。
4.1 只需一个供应者就可以满足吸烟要求
此时使用4个信号量,1个互斥量。
信号量:forsmoker1,forsmoker2,forsmoker3,finish
互斥量:mutex
4.2 两个供应者满足一个吸烟者
信号量:yiforsmoker1,yiforsmoker2,yiforsmoker3,erforsmoker1,erforsmoker2,erforsmoker3
finish1,finish2,finish3
代码实现(一)
seller.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
int get_ipc_id(char *proc_file,key_t key);
int set_sem(key_t sem_key,int sem_val,int sem_flag);
int wait(int sem_id);
int signal(int sem_id);
typedef union semuns {
int val;
} Sem_uns;
key_t mutexkey;
key_t forsmoker1key;
key_t forsmoker2key;
key_t forsmoker3key;
key_t finishkey;
int mutex;
int forsmoker1;
int forsmoker2;
int forsmoker3;
int finish;
int sem_val;
int sem_flg;
int wait(int sem_id)
{
struct sembuf buf;
buf.sem_op = -1;
buf.sem_num = 0;
buf.sem_flg = SEM_UNDO;
if((semop(sem_id,&buf,1)) <0) {
perror("down error ");
exit(EXIT_FAILURE);
} return EXIT_SUCCESS;
}
int signal(int sem_id)
{
struct sembuf buf;
buf.sem_op = 1;
buf.sem_num = 0;
buf.sem_flg = SEM_UNDO;
if((semop(sem_id,&buf,1)) <0) {
perror("up error ");
exit(EXIT_FAILURE);
} return EXIT_SUCCESS;
}
///初始化信号量
int set_sem(key_t sem_key,int sem_val,int sem_flg)
{
int sem_id;
Sem_uns sem_arg;
if((sem_id = semget(sem_key,1,sem_flg)) < 0)
{
perror("semaphore create error");
exit(EXIT_FAILURE);
}
sem_arg.val = sem_val;
if(semctl(sem_id,0,SETVAL,sem_arg) <0)
{
perror("semaphore set error");
exit(EXIT_FAILURE