c语言 - 子进程死亡后,父进程不从 FIFO 读取



所以。我必须从一个命名管道中读取和写入,我试图通过以下操作来实现这一点:父进程将命令写入FIFO,然后等待孩子死亡。子进程读取命令,并在另一个fifo中写入一些内容。父级parent从另一个FIFO读取消息并打印结果。我被限制使用fopen,因为在我的代码中,我在其他地方使用unistd的open,所以我没有nonblock标志。我将在下面附上一个片段。此外,如果我使用";w";标志,则代码完全冻结。我知道先进先出是一种阻碍沟通的方式,但我不明白为什么我的父母不能阅读。提前谢谢。

int main()
{
FILE *fp1;
FILE* fp2;
unlink(FIFO_NAME1);
unlink(FIFO_NAME2);
//FIFO_NAME[1|2] is a macro containing the FIFO path
if(mkfifo(FIFO_NAME1, 0666) == -1)
{
printf("Something went wrong");
return -1;
}
if(mkfifo(FIFO_NAME2, 0666) == -1)
{
printf("Something went wrong");
return -1;
}
while(1)
{
char command[MAX_SIZE];
pid_t pid;
if((pid=fork()) !=0)
{
//parent
fgets(command, MAX_SIZE, stdin);
if((fp1= fopen(FIFO_NAME1, "w")) == NULL)
{
printf("Error");
}
fprintf(fp1, "%s", command);
fclose(fp1);
wait(SIGKILL);
//it never prints this or execute past the wait
printf("Here n");
char response[MAX_SIZE];
if((fp2= fopen(FIFO_NAME2,"r"))==NULL)
perror("");
fgets(response, MAX_SIZE, fp2);
fclose(fp2);
//printf("%s",response);
}

else
{
//child
char msg[MAX_SIZE];
if((fp1 = fopen(FIFO_NAME1, "r")) == NULL)
{
printf("Error");
}
fgets(msg, MAX_SIZE, fp1);
fclose(fp1);

if((fp2= fopen(FIFO_NAME2, "w+")) == NULL)
{
printf("Error");
}
char buffer[MAX_SIZE];
strcpy(buffer,"TEST MESSAGE");

fprintf(fp2, "%s", buffer);
fclose(fp2);

fflush(stdout);
kill(getpid(), SIGKILL);
}
}
}

这里的基本问题是不能半开FIFO。至少,除非您在非阻塞模式下打开它进行读取,而fopen()无法做到这一点。通常,打开一个FIFO进行读取将被阻止,直到相同的FIFO也被打开进行写入,反之亦然

关于FIFO_NAME1,您在这方面还可以。父母打开它写作,孩子打开它阅读。一旦双方都这样做了,他们都会继续。

但随后父级调用wait()(参数也不正确,但这是另一个问题(。父级将不会从该wait成功返回,直到它的一个子级终止为止。只有这样,它才会尝试打开FIFO_NAME2(用于读取(,但由于子进程已经终止,该FIFO不会被任何进程打开用于写入,打开它的尝试将无限期地阻止。

然后是孩子。它成功地打开了第二个FIFO,只是因为您指定了模式"w+",这样子项就可以同时满足对读取器和写入器的要求。然而,这是危险的,因为如果子代实际上没有消耗FIFO中的任何数据,那么它可能会通过尝试向其中写入比内核一次愿意缓冲的数据更多的数据而死锁。此外,它不能实现您的通信目标,因为无法保证FIFO在停止打开读取或写入时会保留孩子写入的数据。事实上,它可能不会。

您需要移动或删除wait()调用,如果选择前者,则需要检查文档,以发现应该传递的参数类型。如果您愿意相信子级不会填充管道的缓冲区,那么您可以将等待移动到父级打开FIFO_NAME2之后,然后再尝试读取任何内容。就其本身而言,子级应该确定在只写模式下打开第二个FIFO,以确保父级和子级在子级开始写入之前都打开该FIFO。

最新更新