山东大学操作系统实验四

smoker_question.h 

#ifndef _SMOKER_QUESTION_H
#define _SMOKER_QUESTION_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <time.h>

// 鏉愭枡绫诲瀷
typedef enum { TOBACCO, PAPER, GLUE } Material;

// 鍒濆鍖栦俊鍙烽噺
int init_sem(int key, int value);

// P鎿嶄綔
void sem_wait(int semid);

// V鎿嶄綔
void sem_signal(int semid);

#endif

smoker_sem.c

#include "smoker_question.h"

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

int init_sem(int key, int value) {
    int semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1) {
        perror("semget failed");
        exit(EXIT_FAILURE);
    }
    
    union semun arg;
    arg.val = value;
    if (semctl(semid, 0, SETVAL, arg) == -1) {
        perror("semctl failed");
        exit(EXIT_FAILURE);
    }
    return semid;
}

void sem_wait(int semid) {
    struct sembuf op = {0, -1, 0};
    semop(semid, &op, 1);
}

void sem_signal(int semid) {
    struct sembuf op = {0, 1, 0};
    semop(semid, &op, 1);
}

prac4.c

#include "smoker_question.h"
#include <sys/wait.h>

#define NUM_SMOKERS 3

// 鐢熶骇鑰呭伐浣滃嚱鏁?
void producer_work() {
    // 鑾峰彇涓変釜淇″彿閲?
    int sem_tobacco = semget(111, 1, 0666);
    int sem_paper = semget(222, 1, 0666);
    int sem_glue = semget(333, 1, 0666);

    srand(time(NULL)); // 鍒濆鍖栭殢鏈虹瀛?

    while (1) {
        // 闅忔満閫夋嫨涓€绉嶇己澶辩殑鏉愭枡(鎻愪緵鍙﹀涓ょ)
        int missing = rand() % 3;

        switch (missing) {
            case 0: // 缂虹儫鑽?鎻愪緵绾稿拰鑳舵按)
                printf("Producer%d: providing PAPER and GLUE\n",getpid());
                sem_signal(sem_tobacco);
                break;
            case 1: // 缂虹焊(鎻愪緵鐑熻崏鍜岃兌姘?
                printf("Producer%d: providing TOBACCO and GLUE\n",getpid());
                sem_signal(sem_paper);
                break;
            case 2: // 缂鸿兌姘?鎻愪緵鐑熻崏鍜岀焊)
                printf("Producer%d: providing TOBACCO and PAPER\n",getpid());
                sem_signal(sem_glue);
                break;
        }

        sleep(1); // 绛夊緟鎶界儫鑰呭畬鎴?
    }
}

// 娑堣垂鑰呭伐浣滃嚱鏁?
void smoker_work(Material material) {
    const char *names[] = {"TOBACCO", "PAPER", "GLUE"};
    
    // 鑾峰彇瀵瑰簲鐨勪俊鍙烽噺
    int semid;
    switch (material) {
        case TOBACCO: semid = semget(111, 1, 0666); break; // 绛夊緟绾稿拰鑳舵按
        case PAPER:   semid = semget(222, 1, 0666); break; // 绛夊緟鐑熻崏鍜岃兌姘?
        case GLUE:    semid = semget(333, 1, 0666); break; // 绛夊緟鐑熻崏鍜岀焊
        default: exit(EXIT_FAILURE);
    }

    while (1) {
        sem_wait(semid); // 绛夊緟闇€瑕佺殑鏉愭枡缁勫悎

        printf("Smoker%d with %s:smoking a cigarette\n",getpid(), names[material]);
        sleep(1); // 妯℃嫙鎶界儫鏃堕棿

        printf("Smoker%d with %s: Done smoking\n",getpid(), names[material]);
    }
}

int main() {
    // 鍒濆鍖栦笁涓俊鍙烽噺
    init_sem(111, 0);  // 绾稿拰鑳舵按
    init_sem(222, 0);  // 鐑熻崏鍜岃兌姘?
    init_sem(333, 0);  // 鐑熻崏鍜岀焊

    // 鍒涘缓涓や釜鐢熶骇鑰呰繘绋?鐖惰繘绋嬪拰绗竴涓瓙杩涚▼)
    pid_t producer_pid = fork();
    if (producer_pid == 0) {
        // 瀛愯繘绋嬩綔涓虹浜屼釜鐢熶骇鑰?
        producer_work();
        exit(0);
    }

    // 鐖惰繘绋嬩綔涓虹涓€涓敓浜ц€?
    pid_t smoker_pids[NUM_SMOKERS];
    int i;
    for ( i = 0; i < NUM_SMOKERS; i++) {
        smoker_pids[i] = fork();
        if (smoker_pids[i] == 0) {
            // 瀛愯繘绋嬩綔涓烘秷璐硅€?
            smoker_work((Material)i);
            exit(0);
        }
    }

    // 鐖惰繘绋嬩篃浣滀负鐢熶骇鑰?
    producer_work();

    // 绛夊緟鎵€鏈夊瓙杩涚▼缁搒
    for ( i = 0; i < NUM_SMOKERS; i++) {
        waitpid(smoker_pids[i], NULL, 0);
    }
    waitpid(producer_pid, NULL, 0);

    return 0;
}

Makefile

cc = gcc
CFLAGS = -Wall -g
TARGET = prac4
SRCS = prac4.c smoker_sem.c

all: $(TARGET)
$(TARGET): $(SRCS)
	$(CC) $(CFLAGS) -o $(TARGET) $(SRCS)
clean:
	rm -f $(TARGET)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值