ipc.h
/* --------------- ipc.h --------------- */
#ifndef IPC_H
#define IPC_H
#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>
#include <unistd.h>
#include <time.h>
#define BUFSZ 256
#define SOFA_CAPACITY 4
#define WAITROOM_CAPACITY 13
#define MAX_CUSTOMERS 20
#define SOFA_QUEUE 1
#define WAITROOM_QUEUE 2
#define ACCOUNT_SEM 3
#define CUSTOMER_SEM 4
typedef struct {
long mtype;
int customer_id;
} Message;
// 鍏变韩鍑芥暟澹版槑
int get_ipc_id(char *proc_file, key_t key);
int set_sem(key_t key, int val);
int set_msgq(key_t key);
void send_message(int qid, long type, int id);
int receive_message(int qid, long type, int flags);
void down(int semid);
void up(int semid);
#endif
ipc.c
/* --------------- ipc.c --------------- */
#include "ipc.h"
int get_ipc_id(char *proc_file, key_t key) {
FILE *pf = fopen(proc_file, "r");
/* 鍘焔et_ipc_id鍑芥暟瀹炵幇 */
}
int set_sem(key_t key, int val) {
int semid;
if((semid = semget(key, 1, IPC_CREAT|0666)) == -1) {
perror("semget");
exit(1);
}
semctl(semid, 0, SETVAL, val);
return semid;
}
int set_msgq(key_t key) {
int qid;
if((qid = msgget(key, IPC_CREAT|0666)) == -1) {
perror("msgget");
exit(1);
}
return qid;
}
void send_message(int qid, long type, int id) {
Message msg = {type, id};
if(msgsnd(qid, &msg, sizeof(msg)-sizeof(long), 0) == -1) {
perror("msgsnd");
}
}
int receive_message(int qid, long type, int flags) {
Message msg;
if(msgrcv(qid, &msg, sizeof(msg)-sizeof(long), type, flags) == -1) {
if(!(flags & IPC_NOWAIT)) perror("msgrcv");
return -1;
}
return msg.customer_id;
}
void down(int semid) {
struct sembuf op = {0, -1, SEM_UNDO};
semop(semid, &op, 1);
}
void up(int semid) {
struct sembuf op = {0, 1, SEM_UNDO};
semop(semid, &op, 1);
}
customer.c
/* --------------- customer.c --------------- */
#include "ipc.h"
int main() {
srand(time(NULL));
key_t sofa_key = 100;
key_t wait_key = 200;
key_t account_sem_key = 300;
key_t customer_sem_key = 400;
// 鍒濆鍖朓PC瀵硅薄
int sofa_qid = set_msgq(sofa_key);
int wait_qid = set_msgq(wait_key);
int account_sem = set_sem(account_sem_key, 1);
int customer_sem = set_sem(customer_sem_key, 0);
int customer_id = 1;
while(1) {
struct msqid_ds sofa_stat, wait_stat;
msgctl(sofa_qid, IPC_STAT, &sofa_stat);
msgctl(wait_qid, IPC_STAT, &wait_stat);
int total = sofa_stat.msg_qnum + wait_stat.msg_qnum;
if(total >= MAX_CUSTOMERS) {
printf("Customer %d: 搴楅摵宸叉弧锛岀寮€\n", customer_id);
customer_id++;
sleep(rand()%3+1);
continue;
}
// 灏濊瘯璁╃瓑鍊欏椤惧鍧愬埌娌欏彂
if(sofa_stat.msg_qnum < SOFA_CAPACITY) {
Message msg;
if(msgrcv(wait_qid, &msg, sizeof(msg)-sizeof(long), WAITROOM_QUEUE, IPC_NOWAIT) > 0) {
msg.mtype = SOFA_QUEUE;
msgsnd(sofa_qid, &msg, sizeof(msg)-sizeof(long), 0);
printf("Customer %d: 浠庣瓑鍊欏绉诲埌娌欏彂\n", msg.customer_id);
continue;
}
}
// 澶勭悊鏂伴【瀹?
if(sofa_stat.msg_qnum < SOFA_CAPACITY) {
send_message(sofa_qid, SOFA_QUEUE, customer_id);
printf("Customer %d: 鍧愬埌娌欏彂\n", customer_id);
} else if(wait_stat.msg_qnum < WAITROOM_CAPACITY) {
send_message(wait_qid, WAITROOM_QUEUE, customer_id);
printf("Customer %d: 杩涘叆绛夊€欏\n", customer_id);
} else {
printf("Customer %d: 鎵€鏈変綅缃凡婊★紝绂诲紑\n", customer_id);
}
customer_id++;
up(customer_sem); // 鍞ら啋鐞嗗彂甯?
sleep(rand()%3+1); // 闅忔満鍒拌揪鏃堕棿
}
return 0;
}
barber.c
/* --------------- barber.c --------------- */
#include "ipc.h"
int main() {
srand(time(NULL));
key_t sofa_key = 100;
key_t account_sem_key = 300;
key_t customer_sem_key = 400;
int sofa_qid = set_msgq(sofa_key);
int account_sem = set_sem(account_sem_key, 1);
int customer_sem = set_sem(customer_sem_key, 0);
for(int i = 0; i < 3; i++) {
if(fork() == 0) {
while(1) {
Message msg;
struct msqid_ds stat;
msgctl(sofa_qid, IPC_STAT, &stat);
if(stat.msg_qnum == 0) {
printf("Barber %d: 娌℃湁椤惧锛岀潯瑙塡n", getpid());
down(customer_sem); // 绛夊緟椤惧鍒版潵
}
if(msgrcv(sofa_qid, &msg, sizeof(msg)-sizeof(long), SOFA_QUEUE, 0) > 0) {
printf("Barber %d: 姝e湪涓洪【瀹?d鐞嗗彂\n", getpid(), msg.customer_id);
sleep(rand()%4+10);
down(account_sem);
printf("Barber %d: 姝e湪鏀跺彇椤惧%d鐨勮垂鐢╘n", getpid(), msg.customer_id);
sleep(1);
up(account_sem);
}
}
exit(0);
}
}
while(wait(NULL) > 0);
return 0;
}
Makefile
# 目标文件
all: customer barber
# 编译 customer
customer: ipc.c customer.c
gcc ipc.c customer.c -o customer
# 编译 barber
barber: ipc.c barber.c
gcc ipc.c barber.c -o barber
# 清理
clean:
rm -f customer barber