我在fork 101失败了。我希望这会分叉一个子进程,并输出子和父printfs:
pid_t fpid;
if ((fpid = fork()) < 0)
{
printf("fork: %s\n", strerror(errno));
exit(-1);
}
if (0 == fpid) // child
{
printf("\nI am the child\n");
}
else
{
printf("\nI am the parent\n");
pid_t wpid;
while ((wpid = waitpid(WAIT_ANY, NULL, 0)))
{
if (errno == ECHILD)
break;
else if (wpid < 0)
printf("wait: %s\n", strerror(errno));
}
}
相反,我得到了这个输出:
我是父母
等待:系统调用中断
所以我的问题是:为什么孩子没有机会生活和奔跑?请不要有人想到孩子们!此外,EINTR来自哪里?显然,这与我的第一个问题有某种关系。
此外,当我在独立程序中运行该代码时,它可以正常工作,但不能在我的更大程序中运行;大型程序可以做些什么来扰乱waitpid?
FWIW这是在OSX 10.9上。
答案 0 :(得分:4)
在OSX上,在fork之前/之后对fork的子端做很多事情是不合法的。请参阅fork man page底部的警告。安全功能列表位于sigaction(2) man page。 printf()
不在其中。
此外,stdout可能已缓冲。 printf()
的结果可能无法刷新。如果你调用exit()
,它会被刷新,但这对于fork的子端也是不合法的。 (使用_exit()
是合适的,但不会刷新打开的流。)实际上,您似乎没有退出子进程,这意味着执行流继续到您的代码的调用者显示,可能会返回到您的其他程序。由于叉子的儿童方面的限制,它可能会卡在那里。
如果你在孩子身上做了类似的事情,你可能会有更多的运气:
const char msg[] = "\nI am the child\n";
write(STDOUT_FILENO, msg, sizeof(msg) - 1);
_exit(0);
最后,我认为您应该将fpid
而不是WAIT_ANY
传递给waitpid()
。您有一个您想要等待的特定子进程。在较大程序的上下文中,您不希望窃取由其他子组件生成的子项终止的通知。而且你总是需要绕过可中断的系统调用,直到它们返回EINTR
以外的其他内容。
答案 1 :(得分:0)
仅检查errno
是否指示了失败,例如通过系统调用返回-1
。
代码应如下所示:
pid_t fpid;
if ((fpid = fork()) < 0)
{
printf("fork: %s\n", strerror(errno));
exit(-1);
}
if (0 == fpid) // child
{
printf("\nI am the child\n");
}
else
{
printf("\nI am the parent\n");
pid_t wpid;
while ((wpid = waitpid(WAIT_ANY, NULL, 0)))
{
if (-1 == wpid)
{
perror("waitpid() failed");
}
else if (wpid == fpid)
{
/* My child ended, so stop waiting for it. */
break;
}
}
}