山东大学操作系统实验五

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值