#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <string.h>
#define SHM_KEY 1234
#define SEM_KEY 5678
struct BufferPool
{
char Buffer[5][100];
int Index[5];
};
// 定义信号量操作结构体
struct sembuf sem_lock = {0, -1, SEM_UNDO};
struct sembuf sem_unlock = {0, 1, SEM_UNDO};
void producer(int shmid, int semid, const char *inputFile)
{
struct BufferPool *buffer = (struct BufferPool *)shmat(shmid, NULL, 0);
FILE *input = fopen(inputFile, "r");
char line[100];
while (fgets(line, sizeof(line), input) != NULL)
{
// 等待可用的缓冲区
semop(semid, &sem_lock, 1);
// 查找可用的缓冲区
int i;
for (i = 0; i < 5; i++)
{
if (buffer->Index[i] == 0)
break;
}
// 写入数据到缓冲区
strcpy(buffer->Buffer[i], line);
buffer->Index[i] = 1;
printf("Producer: Wrote \"%s\" to buffer %d\n", line, i);
// 释放缓冲区的访问权
semop(semid, &sem_unlock, 1);
}
fclose(input);
shmdt(buffer);
}
void consumer(int shmid, int semid, const char *outputFile)
{
struct BufferPool *buffer = (struct BufferPool *)shmat(shmid, NULL, 0);
FILE *output = fopen(outputFile, "w");
while (1)
{
// 等待可消费的缓冲区
semop(semid, &sem_lock, 1);
// 查找可消费的缓冲区
int i;
for (i = 0; i < 5; i++)
{
if (buffer->Index[i] == 1)
break;
}
// 读取数据并写入输出文件
fputs(buffer->Buffer[i], output);
printf("Consumer: Read \"%s\" from buffer %d\n", buffer->Buffer[i], i);
// 重置缓冲区状态
buffer->Index[i] = 0;
// 释放缓冲区的访问权
semop(semid, &sem_unlock, 1);
// 结束条件:如果所有缓冲区都已经被消费,则退出循环
int allConsumed = 1;
for (i = 0; i < 5; i++)
{
if (buffer->Index[i] == 1)
{
allConsumed = 0;
break;
}
}
if (allConsumed)
break;
}
fclose(output);
shmdt(buffer);
}
int main()
{
int shmid, semid;
key_t key;
const char *inputFile = "input.txt";
const char *outputFile = "output.txt";
// 创建共享内存
key = ftok(".", SHM_KEY);
shmid = shmget(key, sizeof(struct BufferPool), IPC_CREAT | 0666);
if (shmid == -1)
{
perror("shmget");
exit(1);
}
// 创建信号量集
key = ftok(".", SEM_KEY);
semid = semget(key, 1, IPC_CREAT | 0666);
if (semid == -1)
{
perror("semget");
exit(1);
}
// 初始化信号量
semctl(semid, 0, SETVAL, 1);
// 创建子进程
pid_t pid = fork();
if (pid == -1)
{
perror("fork");
exit(1);
}
else if (pid == 0)
{
// 子进程作为第一个生产者
producer(shmid, semid, inputFile);
exit(0);
}
// 创建另一个子进程
pid_t pid2 = fork();
if (pid2 == -1)
{
perror("fork");
exit(1);
}
else if (pid2 == 0)
{
// 另一个子进程作为第二个生产者
producer(shmid, semid, inputFile);
exit(0);
}
// 父进程作为第一个消费者
consumer(shmid, semid, outputFile);
// 等待子进程结束
waitpid(pid, NULL, 0);
waitpid(pid2, NULL, 0);
// 删除共享内存和信号量集
shmctl(shmid, IPC_RMID, NULL);
semctl(semid, 0, IPC_RMID);
return 0;
}