在 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 意识到的那样,最后一只填满罐子的蜜蜂在唤醒熊之前并没有把它放回管道,让熊永远等待管道的数据。