#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#define BUFFER_SIZE 100
#define NUM_BUFFERS 5
struct BufferPool {
char Buffer[NUM_BUFFERS][BUFFER_SIZE];
int Index[NUM_BUFFERS];
};
int main() {
// 创建共享内存段
int shmid = shmget(IPC_PRIVATE, sizeof(struct BufferPool), IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(1);
}
// 连接到共享内存段
struct BufferPool *bufferPool = shmat(shmid, NULL, 0);
if (bufferPool == (void *)-1) {
perror("shmat");
exit(1);
}
// 初始化缓冲池结构
memset(bufferPool, 0, sizeof(struct BufferPool));
// 创建信号量集
int semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
if (semid == -1) {
perror("semget");
exit(1);
}
// 初始化信号量集
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
} sem_arg;
sem_arg.val = 1; // 初始化信号量为1,用于互斥访问缓冲池
if (semctl(semid, 0, SETVAL, sem_arg) == -1) {
perror("semctl");
exit(1);
}
// 创建两个生产者进程
for (int i = 0; i < 2; i++) {
pid_t pid = fork();
if (pid == 0) {
// 生产者进程
FILE *inputFile = fopen("input.txt", "r");
if (inputFile == NULL) {
perror("fopen");
exit(1);
}
char line[BUFFER_SIZE];
while (fgets(line, sizeof(line), inputFile) != NULL) {
// 等待缓冲区可分配
struct sembuf sem_op;
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(semid, &sem_op, 1);
// 查找可用的缓冲区
int bufferIndex = -1;
for (int j = 0; j < NUM_BUFFERS; j++) {
if (bufferPool->Index[j] == 0) {
bufferIndex = j;
bufferPool->Index[j] = 1; // 标记缓冲区为已使用
break;
}
}
// 将数据写入缓冲区
strncpy(bufferPool->Buffer[bufferIndex], line, sizeof(bufferPool->Buffer[bufferIndex]));
// 打印生产者工作过程
printf("Producer %d: Wrote '%s' to buffer %d\n", getpid(), line, bufferIndex);
// 释放缓冲区
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop(semid, &sem_op, 1);
}
fclose(inputFile);
exit(0);
} else if (pid == -1) {
perror("fork");
exit(1);
}
}
// 创建两个消费者进程
for (int i = 0; i < 2; i++) {
pid_t pid = fork();
if (pid == 0) {
// 消费者进程
FILE *outputFile = fopen("output.txt", "a");
if (outputFile == NULL) {
perror("fopen");
exit(1);
}
for (int j = 0; j < NUM_BUFFERS; j++) {
// 等待缓冲区可消费
struct sembuf sem_op;
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(semid, &sem_op, 1);
// 检查缓冲区状态
if (bufferPool->Index[j] == 1) {
// 读取数据并写入文件
fprintf(outputFile, "Consumer %d: Read '%s' from buffer %d\n", getpid(), bufferPool->Buffer[j], j);
bufferPool->Index[j] = 0; // 标记缓冲区为可分配
}
// 释放缓冲区
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop(semid, &sem_op, 1);
}
fclose(outputFile);
exit(0);
} else if (pid == -1) {
perror("fork");
exit(1);
}
}
// 等待所有子进程结束
for (int i = 0; i < 4; i++) {
wait(NULL);
}
// 分离共享内存段
shmdt(bufferPool);
// 删除共享内存段
shmctl(shmid, IPC_RMID, NULL);
// 删除信号量集
semctl(semid, 0, IPC_RMID);
return 0;
}