信号量解决进程同步问题生产者消费者问题代码
时间: 2023-08-22 13:05:10 浏览: 146
下面是一个使用信号量解决生产者消费者问题的示例代码,其中生产者进程和消费者进程通过信号量来同步它们的操作,确保它们不会同时访问共享缓冲区:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define KEY 1234
#define BUFFER_SIZE 10
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
// 初始化信号量
int init_sem(int sem_id, int init_val) {
union semun sem_union;
sem_union.val = init_val;
return semctl(sem_id, 0, SETVAL, sem_union);
}
// P 操作
int sem_p(int sem_id) {
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
return semop(sem_id, &sem_b, 1);
}
// V 操作
int sem_v(int sem_id) {
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
return semop(sem_id, &sem_b, 1);
}
// 删除信号量
int del_sem(int sem_id) {
union semun sem_union;
return semctl(sem_id, 0, IPC_RMID, sem_union);
}
int main() {
int sem_id, pid;
key_t key = KEY;
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
int num = 0;
// 创建信号量
sem_id = semget(key, 2, IPC_CREAT | 0666);
if (sem_id == -1) {
perror("create semaphore error");
exit(EXIT_FAILURE);
}
// 初始化信号量的值
if (init_sem(sem_id, 1) == -1 || init_sem(sem_id + 1, 0) == -1) {
perror("init semaphore error");
exit(EXIT_FAILURE);
}
// 创建子进程
pid = fork();
if (pid == -1) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if (pid == 0) {
// 子进程为生产者
while (1) {
sem_p(sem_id);
if (num < BUFFER_SIZE) {
buffer[in] = num++;
in = (in + 1) % BUFFER_SIZE;
printf("producer: produced %d\n", buffer[in]);
}
sem_v(sem_id + 1);
sleep(1);
}
}
else {
// 父进程为消费者
while (1) {
sem_p(sem_id + 1);
if (num > 0) {
printf("consumer: consumed %d\n", buffer[out]);
buffer[out] = 0;
out = (out + 1) % BUFFER_SIZE;
num--;
}
sem_v(sem_id);
sleep(2);
}
}
// 删除信号量
if (del_sem(sem_id) == -1) {
perror("delete semaphore error");
exit(EXIT_FAILURE);
}
if (del_sem(sem_id + 1) == -1) {
perror("delete semaphore error");
exit(EXIT_FAILURE);
}
return 0;
}
```
在这个示例代码中,生产者进程和消费者进程通过调用 `sem_p()` 和 `sem_v()` 函数来进行 P 操作和 V 操作,从而实现对共享缓冲区的互斥访问和同步操作。其中,生产者进程等待信号量 1 并进行 P 操作后,判断缓冲区是否已满,如果未满则将一个元素放入缓冲区,然后进行 V 操作 0 并释放信号量 0;消费者进程等待信号量 0 并进行 P 操作后,判断缓冲区是否为空,如果非空则从缓冲区中取出一个元素,然后进行 V 操作 1 并释放信号量 1。
阅读全文