这是制作人。
// 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...
发言找不到读者,发送。从我theory here开始, open()(speak.c)将被阻止,直到 open()(tick.c)被打开。反之亦然。所以我想有一个僵局或发生的事情。我需要一个解决方案。
答案 0 :(得分:0)
看起来你在读者与作者之间存在竞争条件。
要解决此问题,您需要一种在编写器处于“活动”状态之前不启动阅读器的方法。为此,我建议在编写器准备好的时候制作一个管道并写入它。然后,当从fork的读取端读取成功时,fifo准备好并且读者应该工作。
你需要在这里使用分叉,因为在父进程和子进程之间协调互斥是非常重要的,并且正确完成管道更容易。
此外,您曾两次致电mknod()
。当然,它会以errno == EEXIST
返回-1,但要更加小心。为避免这种情况,请使读写器成为一个以路径为参数的函数。
将您的作者重写为int speak(const char *fifo, int pipefd)
,将您的读者重写为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。
请不要逐字使用我的代码,因为为了简洁起见,我省略了错误检查。
答案 1 :(得分:0)
它在我的环境中运行正常。如果读者和作者准备就绪,开放将返回。因为open是被阻止的,所以在我看来,mknod功能是成功的。可能是你在不同的道路上执行这两个过程。