生产者消费者c语言代码_生产者消费者问题、父子进程、信号量(IPC机制):代码分享...
时间: 2023-06-17 12:05:26 浏览: 140
pv操作解决生产者与消费者问题
下面是一个基于信号量实现的生产者消费者问题的C语言代码,其中使用了父子进程模型。
```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#define N 10 // 缓冲区大小
#define P_NUM 3 // 生产者数目
#define C_NUM 2 // 消费者数目
union semun{
int val;
struct semid_ds *buf;
ushort *array;
};
int semid, shmid;
char *shmaddr;
void P(int semid, int index)
{
struct sembuf sem;
sem.sem_num = index;
sem.sem_op = -1;
sem.sem_flg = 0;
semop(semid, &sem, 1);
}
void V(int semid, int index)
{
struct sembuf sem;
sem.sem_num = index;
sem.sem_op = 1;
sem.sem_flg = 0;
semop(semid, &sem, 1);
}
void init()
{
semid = semget(IPC_PRIVATE, 3, IPC_CREAT | 0666);
union semun arg;
arg.val = 0;
semctl(semid, 0, SETVAL, arg); // 缓冲区空闲数目
arg.val = N;
semctl(semid, 1, SETVAL, arg); // 缓冲区占用数目
arg.val = 1;
semctl(semid, 2, SETVAL, arg); // 互斥信号量
shmid = shmget(IPC_PRIVATE, N, IPC_CREAT | 0666);
shmaddr = (char*)shmat(shmid, NULL, 0);
}
void producer(int id)
{
int i, j;
char c;
for (i = 0; i < 5; i++) {
c = 'A' + i;
P(semid, 1); // 占用一个缓冲区
P(semid, 2); // 获取互斥信号量
for (j = 0; j < N; j++) {
if (shmaddr[j] == 0) {
shmaddr[j] = c;
printf("producer %d produced %c\n", id, c);
break;
}
}
V(semid, 2); // 释放互斥信号量
V(semid, 0); // 空闲缓冲区数目加1
sleep(1);
}
}
void consumer(int id)
{
int i, j;
char c;
for (i = 0; i < 5; i++) {
P(semid, 0); // 获取一个空闲缓冲区
P(semid, 2); // 获取互斥信号量
for (j = 0; j < N; j++) {
if (shmaddr[j] != 0) {
c = shmaddr[j];
shmaddr[j] = 0;
printf("consumer %d consumed %c\n", id, c);
break;
}
}
V(semid, 2); // 释放互斥信号量
V(semid, 1); // 占用缓冲区数目减1
sleep(1);
}
}
int main()
{
int i;
init();
for (i = 0; i < P_NUM; i++) {
if (fork() == 0) {
producer(i);
exit(0);
}
}
for (i = 0; i < C_NUM; i++) {
if (fork() == 0) {
consumer(i);
exit(0);
}
}
for (i = 0; i < P_NUM + C_NUM; i++) {
wait(NULL);
}
semctl(semid, 0, IPC_RMID);
semctl(semid, 1, IPC_RMID);
semctl(semid, 2, IPC_RMID);
shmdt(shmaddr);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
```
在代码中,我们使用了三个信号量,分别表示缓冲区空闲数目、缓冲区占用数目和互斥信号量。生产者和消费者在操作缓冲区时需要获取缓冲区空闲数目和缓冲区占用数目的信号量,以及互斥信号量。
在初始化时,我们使用semget函数创建了一个信号量集,然后分别设置了三个信号量的初值。我们还使用shmget函数创建了一个共享内存块,并使用shmat函数将其映射到当前进程的地址空间中。
在生产者和消费者函数中,我们使用P和V函数分别实现了信号量的P和V操作。生产者先占用一个缓冲区,然后获取互斥信号量,向缓冲区中添加一个字符,最后释放互斥信号量和空闲缓冲区数目的信号量。消费者先获取一个空闲缓冲区的信号量,然后获取互斥信号量,从缓冲区中取出一个字符,最后释放互斥信号量和占用缓冲区数目的信号量。
在主函数中,我们使用fork函数创建了多个生产者和消费者进程,并使用wait函数等待所有子进程结束后释放信号量和共享内存块。
这个代码可以在Linux系统上编译运行。
阅读全文