Linux共享内存实现生产者-消费者问题
时间: 2024-02-12 15:39:47 浏览: 29
Linux共享内存是一种进程间通信的方式,也可以用来解决生产者-消费者问题。下面是一个基本的共享内存实现生产者-消费者问题的例子:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <sys/shm.h>
#include <semaphore.h>
#define SIZE 10 // 缓冲区大小
// 共享内存结构体
typedef struct {
char buf[SIZE][256]; // 缓冲区
int head; // 缓冲区头指针
int tail; // 缓冲区尾指针
} shm_struct;
// 信号量
sem_t *sem_mutex; // 互斥信号量,用来保证对缓冲区的互斥访问
sem_t *sem_empty; // 空缓冲区信号量,用来表示可用的空缓冲区数量
sem_t *sem_full; // 满缓冲区信号量,用来表示已经存储的数据量
// 共享内存ID和指针
int shmid;
shm_struct *shm_ptr;
// 生产者线程
void *producer(void *arg)
{
int i = 0;
char *str = (char *)arg;
while (1) {
sem_wait(sem_empty); // 等待空缓冲区
sem_wait(sem_mutex); // 互斥访问缓冲区
sprintf(shm_ptr->buf[shm_ptr->tail], "%s %d", str, i++);
shm_ptr->tail = (shm_ptr->tail + 1) % SIZE; // 缓冲区指针后移
sem_post(sem_mutex); // 释放互斥信号量
sem_post(sem_full); // 释放满缓冲区信号量
sleep(rand() % 2 + 1); // 随机休眠一段时间
}
pthread_exit(NULL);
}
// 消费者线程
void *consumer(void *arg)
{
int i = 0;
while (1) {
sem_wait(sem_full); // 等待满缓冲区
sem_wait(sem_mutex); // 互斥访问缓冲区
printf("consumer[%d]: %s\n", i++, shm_ptr->buf[shm_ptr->head]);
shm_ptr->head = (shm_ptr->head + 1) % SIZE; // 缓冲区指针后移
sem_post(sem_mutex); // 释放互斥信号量
sem_post(sem_empty); // 释放空缓冲区信号量
sleep(rand() % 2 + 1); // 随机休眠一段时间
}
pthread_exit(NULL);
}
int main()
{
// 初始化共享内存
shmid = shmget(IPC_PRIVATE, sizeof(shm_struct), 0666 | IPC_CREAT);
if (shmid < 0) {
perror("shmget");
exit(1);
}
shm_ptr = (shm_struct *)shmat(shmid, NULL, 0);
if (shm_ptr == (void *)-1) {
perror("shmat");
exit(1);
}
shm_ptr->head = 0;
shm_ptr->tail = 0;
// 初始化信号量
sem_mutex = sem_open("/sem_mutex", O_CREAT, 0666, 1);
sem_empty = sem_open("/sem_empty", O_CREAT, 0666, SIZE);
sem_full = sem_open("/sem_full", O_CREAT, 0666, 0);
// 创建生产者线程和消费者线程
pthread_t tid_producer, tid_consumer;
pthread_create(&tid_producer, NULL, producer, (void *)"producer");
pthread_create(&tid_consumer, NULL, consumer, NULL);
// 等待线程结束
pthread_join(tid_producer, NULL);
pthread_join(tid_consumer, NULL);
// 删除信号量和共享内存
sem_unlink("/sem_mutex");
sem_unlink("/sem_empty");
sem_unlink("/sem_full");
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
```
该程序中,定义了一个大小为10的缓冲区结构体`shm_struct`,其中包含了缓冲区`buf`和头尾指针`head`和`tail`。同时,定义了三个信号量`sem_mutex`、`sem_empty`和`sem_full`,分别用来表示互斥访问缓冲区、可用的空缓冲区数量和已经存储的数据量。
生产者线程中,不断等待空缓冲区和互斥访问缓冲区信号量,然后向缓冲区中写入数据,并将缓冲区指针后移。最后释放互斥信号量和满缓冲区信号量,并随机休眠一段时间。
消费者线程中,不断等待满缓冲区和互斥访问缓冲区信号量,然后从缓冲区中读取数据,并将缓冲区指针后移。最后释放互斥信号量和空缓冲区信号量,并随机休眠一段时间。
在`main`函数中,首先初始化共享内存和信号量,然后创建生产者线程和消费者线程。最后等待线程结束,删除信号量和共享内存。