使用多线程/进程和System V信号量解决生产者消费者问题:有一个长度为N的缓冲池(共享内存)被生产者和消费者共同使用。只要缓冲池未满,生产者就可以将消息送入缓冲池;只要缓冲池不空,消费者便可从缓冲池中取走一个消息。生产者向缓冲池放入消息的同时,消费者不能操作缓冲池,反之亦然。(提示:两个C文件,consumer.c,producer.c),
时间: 2023-11-27 20:50:19 浏览: 281
以下是使用多线程和System V信号量解决生产者消费者问题的示例代码:
producer.c:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#define N 5 // 缓冲池的大小
#define PRODUCER_SEM 0 // 生产者信号量的编号
#define CONSUMER_SEM 1 // 消费者信号量的编号
// 定义联合体以便使用semctl函数
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
int main() {
key_t key = ftok("./", 'p'); // 生成一个键值以便获取共享内存和信号量
int shmid = shmget(key, N * sizeof(int), IPC_CREAT | 0666); // 获取共享内存
int semid = semget(key, 2, IPC_CREAT | 0666); // 获取信号量
union semun arg; // 定义联合体以便使用semctl函数
arg.val = 1; // 初始化生产者信号量的值为1
semctl(semid, PRODUCER_SEM, SETVAL, arg); // 设置生产者信号量的值
arg.val = 0; // 初始化消费者信号量的值为0
semctl(semid, CONSUMER_SEM, SETVAL, arg); // 设置消费者信号量的值
int *buffer = (int *) shmat(shmid, NULL, 0); // 将共享内存映射到进程的地址空间
int item = 0; // 初始化生产者要生产的物品
while (1) {
sleep(rand() % 3); // 随机等待一段时间
printf("Producer: waiting to produce item %d\n", item);
semop(semid, & (struct sembuf) {PRODUCER_SEM, -1, 0}, 1); // P操作生产者信号量
buffer[item] = item; // 在缓冲池中放入物品
printf("Producer: produced item %d\n", item);
item = (item + 1) % N; // 更新要生产的物品
semop(semid, & (struct sembuf) {CONSUMER_SEM, 1, 0}, 1); // V操作消费者信号量
}
shmdt(buffer); // 将共享内存从进程的地址空间中分离
shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
semctl(semid, 0, IPC_RMID); // 删除信号量
return 0;
}
```
consumer.c:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#define N 5 // 缓冲池的大小
#define PRODUCER_SEM 0 // 生产者信号量的编号
#define CONSUMER_SEM 1 // 消费者信号量的编号
// 定义联合体以便使用semctl函数
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
int main() {
key_t key = ftok("./", 'p'); // 生成一个键值以便获取共享内存和信号量
int shmid = shmget(key, N * sizeof(int), IPC_CREAT | 0666); // 获取共享内存
int semid = semget(key, 2, IPC_CREAT | 0666); // 获取信号量
union semun arg; // 定义联合体以便使用semctl函数
int *buffer = (int *) shmat(shmid, NULL, 0); // 将共享内存映射到进程的地址空间
while (1) {
sleep(rand() % 3); // 随机等待一段时间
printf("Consumer: waiting to consume item\n");
semop(semid, & (struct sembuf) {CONSUMER_SEM, -1, 0}, 1); // P操作消费者信号量
int item = buffer[0]; // 从缓冲池中取出物品
for (int i = 0; i < N - 1; i++) {
buffer[i] = buffer[i + 1]; // 移动缓冲池中的物品
}
buffer[N - 1] = -1; // 最后一个位置置为-1表示空闲
printf("Consumer: consumed item %d\n", item);
semop(semid, & (struct sembuf) {PRODUCER_SEM, 1, 0}, 1); // V操作生产者信号量
}
shmdt(buffer); // 将共享内存从进程的地址空间中分离
shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
semctl(semid, 0, IPC_RMID); // 删除信号量
return 0;
}
```
在终端中编译并运行producer.c和consumer.c:
```
$ gcc -o producer producer.c -lpthread -lrt
$ gcc -o consumer consumer.c -lpthread -lrt
$ ./producer &
$ ./consumer &
```
程序将会不断地输出生产者和消费者的操作,直到手动停止程序。
阅读全文