在 C 中跨进程 Cond 等待和信号
Cond wait and signal across processes in C
我正在尝试用流程(熊-蜜蜂)复制一个简单的生产者-消费者问题。到目前为止,我能够同步蜜蜂,以便当时只有一只蜜蜂生产蜂蜜。不过,到了熊吃的时候,似乎就卡在了等待状态。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/mman.h>
typedef struct Pot {
int honey;
int size;
} Pot;
pthread_mutex_t * pot_lock = NULL;
pthread_mutexattr_t lock_properties;
pthread_cond_t * can_use_pot = NULL;
pthread_condattr_t condition_properties;
int main(int arc, char* argv[]){
int fd[2];
int total_bees = 10;
int created_bees = 0;
pthread_mutexattr_init(&lock_properties);
pthread_mutexattr_setpshared(&lock_properties, PTHREAD_PROCESS_SHARED);
//edit: previously using malloc
pot_lock = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS, -1, 0);
//---
pthread_mutex_init(pot_lock, &lock_properties);
pthread_condattr_init(&condition_properties);
pthread_condattr_setpshared(&condition_properties, PTHREAD_PROCESS_SHARED);
//edit: previously using malloc
can_use_pot = (pthread_cond_t*)mmap(NULL, sizeof(pthread_cond_t), PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS, -1, 0);
//---
pthread_cond_init(can_use_pot, &condition_properties);
if(pipe(fd) == -1){
printf("An error ocurred opening pipe\n");
return -1;
}
pthread_mutex_lock(pot_lock);
printf("[Bear] Places the shared pot\n");
Pot p = {0, 10};
if(write(fd[1], &p, sizeof(Pot)) == -1){
printf("An error ocurred writing pipe\n");
return -1;
}
pthread_mutex_unlock(pot_lock);
int id = -1;
while(created_bees < total_bees && id != 0){
id = fork();
created_bees++;
}
if(id == 0){
while(1 == 1){
pthread_mutex_lock(pot_lock);
Pot p;
if(read(fd[0], &p, sizeof(Pot)) == -1){
printf("An error ocurred reading pipe\n");
return -1;
}
if(p.honey >= p.size){
printf("[Bee] Pot is full. Signals bear\n");
//edit 2: I was not returning the pot to the pipe
if(write(fd[1], &p, sizeof(Pot)) == -1){
printf("An error ocurred writing pipe\n");
return -1;
}
//---
pthread_cond_signal(can_use_pot);
}
else{
sleep(1);
p.honey = p.honey +1;
printf("[Bee] Places honey in the pot [%d]\n", p.honey);
if(write(fd[1], &p, sizeof(Pot)) == -1){
printf("An error ocurred writing pipe\n");
return -1;
}
}
pthread_mutex_unlock(pot_lock);
}
}
else{
while(1 == 1){
printf("[Bear] Falls asleep\n");
pthread_mutex_lock(pot_lock);
pthread_cond_wait(can_use_pot, pot_lock);
Pot p;
if(read(fd[0], &p, sizeof(Pot)) == -1){
printf("An error ocurred reading pipe\n");
return -1;
}
sleep(3);
printf("[Bear] Wakes up and eat [%d]", p.honey);
p.honey = 0;
if(write(fd[1], &p, sizeof(Pot)) == -1){
printf("An error ocurred writing pipe\n");
return -1;
}
pthread_mutex_unlock(pot_lock);
}
}
}
我得到以下输出
[Bear] Places the shared pot
[Bear] Falls asleep
[Bee] Places honey in the pot [1]
[Bee] Places honey in the pot [2]
[Bee] Places honey in the pot [3]
[Bee] Places honey in the pot [4]
[Bee] Places honey in the pot [5]
[Bee] Places honey in the pot [6]
[Bee] Places honey in the pot [7]
[Bee] Places honey in the pot [8]
[Bee] Places honey in the pot [9]
[Bee] Places honey in the pot [10]
[Bee] Pot is full. Signals bear
然后它停留在那里,其他时候重复最后一条信息。
根据我的理解,在调用 pthread_cond_signal 并释放锁后,熊可能会醒来并完成他的工作。起初我以为熊可能没有机会获得锁,所以我尝试添加第二个条件来告诉蜜蜂什么时候可以生产,但它没有用。
编辑 1:如前所述,我将互斥锁和 cond 初始化的 malloc 调用更改为 mmap,我再次陷入等待熊醒来的困境。
正如@StaceyGirl 所指出的,必须使用共享内存 (mmap) 来初始化互斥体和条件
此外,正如@KamilCuk 意识到的那样,最后一只填满罐子的蜜蜂在唤醒熊之前并没有把它放回管道,让熊永远等待管道的数据。
我正在尝试用流程(熊-蜜蜂)复制一个简单的生产者-消费者问题。到目前为止,我能够同步蜜蜂,以便当时只有一只蜜蜂生产蜂蜜。不过,到了熊吃的时候,似乎就卡在了等待状态。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/mman.h>
typedef struct Pot {
int honey;
int size;
} Pot;
pthread_mutex_t * pot_lock = NULL;
pthread_mutexattr_t lock_properties;
pthread_cond_t * can_use_pot = NULL;
pthread_condattr_t condition_properties;
int main(int arc, char* argv[]){
int fd[2];
int total_bees = 10;
int created_bees = 0;
pthread_mutexattr_init(&lock_properties);
pthread_mutexattr_setpshared(&lock_properties, PTHREAD_PROCESS_SHARED);
//edit: previously using malloc
pot_lock = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS, -1, 0);
//---
pthread_mutex_init(pot_lock, &lock_properties);
pthread_condattr_init(&condition_properties);
pthread_condattr_setpshared(&condition_properties, PTHREAD_PROCESS_SHARED);
//edit: previously using malloc
can_use_pot = (pthread_cond_t*)mmap(NULL, sizeof(pthread_cond_t), PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS, -1, 0);
//---
pthread_cond_init(can_use_pot, &condition_properties);
if(pipe(fd) == -1){
printf("An error ocurred opening pipe\n");
return -1;
}
pthread_mutex_lock(pot_lock);
printf("[Bear] Places the shared pot\n");
Pot p = {0, 10};
if(write(fd[1], &p, sizeof(Pot)) == -1){
printf("An error ocurred writing pipe\n");
return -1;
}
pthread_mutex_unlock(pot_lock);
int id = -1;
while(created_bees < total_bees && id != 0){
id = fork();
created_bees++;
}
if(id == 0){
while(1 == 1){
pthread_mutex_lock(pot_lock);
Pot p;
if(read(fd[0], &p, sizeof(Pot)) == -1){
printf("An error ocurred reading pipe\n");
return -1;
}
if(p.honey >= p.size){
printf("[Bee] Pot is full. Signals bear\n");
//edit 2: I was not returning the pot to the pipe
if(write(fd[1], &p, sizeof(Pot)) == -1){
printf("An error ocurred writing pipe\n");
return -1;
}
//---
pthread_cond_signal(can_use_pot);
}
else{
sleep(1);
p.honey = p.honey +1;
printf("[Bee] Places honey in the pot [%d]\n", p.honey);
if(write(fd[1], &p, sizeof(Pot)) == -1){
printf("An error ocurred writing pipe\n");
return -1;
}
}
pthread_mutex_unlock(pot_lock);
}
}
else{
while(1 == 1){
printf("[Bear] Falls asleep\n");
pthread_mutex_lock(pot_lock);
pthread_cond_wait(can_use_pot, pot_lock);
Pot p;
if(read(fd[0], &p, sizeof(Pot)) == -1){
printf("An error ocurred reading pipe\n");
return -1;
}
sleep(3);
printf("[Bear] Wakes up and eat [%d]", p.honey);
p.honey = 0;
if(write(fd[1], &p, sizeof(Pot)) == -1){
printf("An error ocurred writing pipe\n");
return -1;
}
pthread_mutex_unlock(pot_lock);
}
}
}
我得到以下输出
[Bear] Places the shared pot
[Bear] Falls asleep
[Bee] Places honey in the pot [1]
[Bee] Places honey in the pot [2]
[Bee] Places honey in the pot [3]
[Bee] Places honey in the pot [4]
[Bee] Places honey in the pot [5]
[Bee] Places honey in the pot [6]
[Bee] Places honey in the pot [7]
[Bee] Places honey in the pot [8]
[Bee] Places honey in the pot [9]
[Bee] Places honey in the pot [10]
[Bee] Pot is full. Signals bear
然后它停留在那里,其他时候重复最后一条信息。 根据我的理解,在调用 pthread_cond_signal 并释放锁后,熊可能会醒来并完成他的工作。起初我以为熊可能没有机会获得锁,所以我尝试添加第二个条件来告诉蜜蜂什么时候可以生产,但它没有用。
编辑 1:如前所述,我将互斥锁和 cond 初始化的 malloc 调用更改为 mmap,我再次陷入等待熊醒来的困境。
正如@StaceyGirl 所指出的,必须使用共享内存 (mmap) 来初始化互斥体和条件
此外,正如@KamilCuk 意识到的那样,最后一只填满罐子的蜜蜂在唤醒熊之前并没有把它放回管道,让熊永远等待管道的数据。