在linux下创建三个生产进程一个消费者进程共享长度为10KB的环形公共缓冲区,描述代码注释等\
时间: 2024-05-16 17:17:50 浏览: 73
下面是一个简单的实现,其中使用了共享内存和信号量来实现进程间的同步和通信。注释也在代码中进行了说明。
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define BUFFER_SIZE 10240 // 缓冲区大小为10KB
#define MAX_PRODUCER 3 // 生产者进程数量
typedef struct {
int head; // 缓冲区头指针
int tail; // 缓冲区尾指针
char buffer[BUFFER_SIZE]; // 缓冲区
} ring_buffer;
// 定义信号量的操作
static void sem_wait(int sem_id) {
struct sembuf sem_op = {0};
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(sem_id, &sem_op, 1);
}
static void sem_signal(int sem_id) {
struct sembuf sem_op = {0};
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop(sem_id, &sem_op, 1);
}
int main() {
int shmid; // 共享内存ID
ring_buffer *buffer; // 指向共享内存缓冲区的指针
int semid; // 信号量ID
key_t key; // 用于生成共享内存和信号量的key
pid_t pid; // 进程ID
int i, j; // 循环计数器
// 生成key
key = ftok(".", 'a');
if (key == -1) {
perror("ftok");
exit(EXIT_FAILURE);
}
// 创建共享内存
shmid = shmget(key, sizeof(ring_buffer), IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(EXIT_FAILURE);
}
// 连接共享内存
buffer = (ring_buffer*)shmat(shmid, NULL, 0);
if (buffer == (void*) -1) {
perror("shmat");
exit(EXIT_FAILURE);
}
// 初始化缓冲区
buffer->head = buffer->tail = 0;
// 创建信号量
semid = semget(key, 1, IPC_CREAT | 0666);
if (semid == -1) {
perror("semget");
exit(EXIT_FAILURE);
}
// 初始化信号量
semctl(semid, 0, SETVAL, 1);
// 创建生产者进程
for (i = 0; i < MAX_PRODUCER; i++) {
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) { // 子进程
srand(getpid()); // 使用进程ID作为随机数种子
for (j = 0; j < 10; j++) { // 生产10个数据
sem_wait(semid); // 等待信号量
buffer->buffer[buffer->tail++] = rand() % 256; // 生产数据
buffer->tail %= BUFFER_SIZE; // 环形缓冲区
printf("Producer %d produced data.\n", i + 1);
sem_signal(semid); // 发送信号量
sleep(1); // 等待1秒钟
}
exit(EXIT_SUCCESS);
}
}
// 创建消费者进程
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) { // 子进程
int count = 0;
while (count < 30) { // 消费30个数据
sem_wait(semid); // 等待信号量
if (buffer->head != buffer->tail) { // 缓冲区非空
printf("Consumer consumed data: %d\n", buffer->buffer[buffer->head++]);
buffer->head %= BUFFER_SIZE; // 环形缓冲区
count++;
}
sem_signal(semid); // 发送信号量
sleep(1); // 等待1秒钟
}
exit(EXIT_SUCCESS);
}
// 等待所有子进程结束
for (i = 0; i < MAX_PRODUCER + 1; i++) {
wait(NULL);
}
// 删除共享内存和信号量
shmctl(shmid, IPC_RMID, NULL);
semctl(semid, 0, IPC_RMID);
return 0;
}
```
需要说明的是,这只是一个简单的实现,实际上还需要考虑更多的因素,比如进程之间的互斥和同步、缓冲区满和空时的处理等等。
阅读全文