【发布时间】:2018-02-28 04:48:22
【问题描述】:
我正在分叉一个孩子,它将运行一个无限循环并做一些事情。当孩子处于“就绪”状态时,文本将使用 printf 打印到标准输出。我正在用管道重定向孩子的标准输出,以便父母可以看到它。当此文本打印时,我希望父级被解除阻止。
问题似乎是即使在 printf() 调用之后 read() 调用也会保持阻塞。
这是我正在使用的一些示例代码:
父母:
#include <stdio.h>
#include <unistd.h>
int main()
{
int fd[2];
pipe(fd);
char buffer[256];
switch(fork())
{
case -1:
printf("fork failed\n");
_exit(1);
case 0:
printf("Starting progtest...\n");
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
close(fd[1]);
execl("progtest", "progtest", NULL);
perror("exec failed");
_exit(1);
}
close(fd[1]);
read(fd[0], &buffer, sizeof(buffer));
close(fd[0]);
printf("buffer: %s\n", buffer);
}
孩子:
#include <stdio.h>
int main()
{
printf("ready\n");
while(1)
{
// stuff happens here
}
return 0;
}
我很确定管道设置正确。如果我删除无限循环,父级将解除阻塞并打印“就绪”。
有什么方法可以在孩子还在跑步时使用 read() 吗?我是否通过使用管道错误地解决了这个问题?我需要使用两条不同的状态消息执行此操作两次。
【问题讨论】:
-
可能是缓冲问题。在每个
printf之后尝试fflush(stdout)。 -
@melpomene 这适用于这个示例,但我希望得到一个不会对子源进行大量更改的答案(整个循环中有很多打印语句)
-
您可以使用
setvbuf(stdout, NULL, _IONBF, 0);完全关闭输出缓冲。 -
@Geoffrey 这两个解决方案都解决了示例代码的问题,但它们似乎并没有做我正在寻找的事情(而且看起来 read 函数并不意味着工作我想要的方式)。当我在我的实际子程序上尝试这个时,读取将挂起等待更多的写入。我想读取在下一个写入标准输出的实例上返回,而不是所有未来的输出到标准输出
-
啊,我明白了。
read将读取最多 N 个字节或直到 EOF,您可能想要查看getline。如果失败,您可以使用select在尝试读取之前确定文件描述符上是否有要读取的数据。从文件描述符读取时,无论是文件、套接字还是管道,您都必须考虑读取比您想要的更多的数据。通常这是通过在每条消息中发送一个包含消息长度的标头来完成的。我会用一个例子提出一个答案。
标签: c pipe fork parent-child