gpt4 book ai didi

c - IPC FIFO 生产者-消费者死锁

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:38:59 25 4
gpt4 key购买 nike

这是制作人。

// speak.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#define FIFO_NAME "american_maid"

int main(void)
{
char s[300];
int num, fd;

mknod(FIFO_NAME, S_IFIFO | 0666, 0);

printf("waiting for readers...\n");
fd = open(FIFO_NAME, O_WRONLY);
printf("got a reader--type some stuff\n");

while (gets(s), !feof(stdin)) {
if ((num = write(fd, s, strlen(s))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", num);
}

return 0;
}

这就是消费者。

//tick.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#define FIFO_NAME "american_maid"

int main(void)
{
char s[300];
int num, fd;

mknod(FIFO_NAME, S_IFIFO | 0666, 0);

printf("waiting for writers...\n");
fd = open(FIFO_NAME, O_RDONLY);
printf("got a writer\n");

do {
if ((num = read(fd, s, 300)) == -1)
perror("read");
else {
s[num] = '\0';
printf("tick: read %d bytes: \"%s\"\n", num, s);
}
} while (num > 0);

return 0;
}

当我运行它们时,Producer 输出,

waiting for readers...

和消费者产出,

waiting for writers...

speak 找不到读者,打勾。来自 theory here我明白了,open() (speak.c) 将一直​​被阻塞,直到 open() (tick.c) 打开。反之亦然。所以我猜想有一个僵局或发生了什么事。我需要一个解决方案。

最佳答案

看起来您在读者和作者之间存在竞争条件。

要解决此问题,您需要一种在编写器处于“事件状态”之前不启动读取器的方法。为此,我建议制作一个管道并在编写器准备好时写入它。然后,当从 fork 的读取端读取成功时,fifo 准备就绪,读取器应该工作。

您需要在此处使用 fork,因为协调父进程和子进程之间的互斥量非常重要,而且正确完成管道更容易。

此外,您调用了两次 mknod()。当然,它会返回 -1 和 errno == EEXIST,但要更加小心。为避免这种情况,让读取器和写入器成为一个以路径作为参数的函数。

将 writer 重写为 int speak(const char *fifo, int pipefd),将 reader 重写为 int tick(const char *fifo)

然后像这样制作一个包装器:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

const char fifo_name[] /* = ... */;

int speak(const char *fifo, int pipefd);
int tick(const char *fifo);

int main() {
int pipefd[2];
pipe(pipefd);

mknod(fifo_name, S_IFIFO | 0666, 0);

if (fork() == 0) {
close(pipefd[0]);
return speak(fifo_name, pipefd[1]);
} else {
close(pipefd[1]);
char foo;
read(pipefd[0], &foo, 1);
return tick(fifo_name);
}
}

修改您的编写器以在创建 fifo 后(即在调用 open(..., O_WRONLY) 之后)向传递的 fd 打印一个字节(任何内容)。

不要逐字使用我的代码,因为为了简洁起见,我省略了错误检查。

关于c - IPC FIFO 生产者-消费者死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10570184/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com