【发布时间】:2020-06-05 11:00:35
【问题描述】:
我正在尝试使用流程(熊-蜂蜜-蜜蜂)复制一个简单的生产者-消费者问题。到目前为止,我能够同步蜜蜂,以便当时只有一只蜜蜂生产蜂蜜。然而,到了熊吃东西的时候,它似乎陷入了等待状态。
这是我的代码:
#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:正如所指出的,我将 mutex 和 cond 初始化的 malloc 调用更改为 mmap,我再次陷入等待熊醒来。
【问题讨论】:
-
您的内存不在进程之间共享。您需要使用
mmap(而不是malloc)来创建共享映射并将所有数据放在那里。 -
@StaceyGirl 感谢您指出这一点,我发现的进程范围互斥锁的示例只是告诉我分配内存,它必须是共享内存。我已经将 malloc 更改为 mmap,但是我卡在同一步骤(输出相同)。
-
输出中是否没有
[Bear] Falls asleep?请将\n添加到您的printfs 以刷新输出... -
你的蜜蜂在同一个管道上读写。在每个
write(fd[1]之后蜜蜂都会read(fd[0]。熊没有什么可以读的,一切都被蜜蜂读了。你的熊在read(fd[0]上阻塞等待——管道是空的。我很难理解,如果蜜蜂只生产蜂蜜,为什么它会从管道中读取? -
当然,然后“保存”/“存储”
thread_cond_signal(can_use_pot);之前的蜜罐。也就是说,write(fd[1]可以放在if之后。但是,对于sleep(1)来说,在互斥锁被阻止的情况下仍然很奇怪——整个想法是让生产者在不阻止其他人的情况下进行生产。我建议重构代码并编写一些函数,例如pot_is_emptypot_add_onepot_take_one- 这样会更容易。
标签: c process clang mutex semaphore