【发布时间】:2013-12-02 18:18:09
【问题描述】:
我的教科书给出了以下主要例程:
int main()
{
if(fork() == 0)
{
printf("a");
}
else
{
printf("b");
waitpid(-1, NULL, 0);
}
printf("c");
exit(0);
}
它询问可能的输出是什么,我找到了 3 个:
abcc:操作系统选择首先执行的子进程,并打印“a”。然后,操作系统暂停子进程并恢复父进程,打印“b”。然后父必须等到子完成,子打印“c”,最后父打印“c”。
bacc:操作系统选择首先运行的父进程,并打印“b”。然后父母必须等待孩子完成并打印“ac”。然后父级打印“c”。
acbc:操作系统选择子节点先运行直到完成,打印“ac”。然后父进程运行完成,打印“bc”。
但是,教科书中还列出了一个答案,bcac。我不明白这是怎么可能的,因为如果首先打印 b,那么父母必须等待孩子继续,然后打印“ac”,然后父母会打印“c”,给出我已经列出的 bacc .有什么我遗漏的吗,或者说只有 3 个可能的输出是否正确?
【问题讨论】:
-
就像 acbc 一样,父叉子完成,然后子叉子完成,bcac 是子叉子完成,然后父叉子完成。 bcac 是 false (b) > 外部条件 (c) > 退出 > true (a) > 外部条件 (c) > 退出的结果
-
我认为
fork(或printf)失败的情况不考虑? -
我认为你是对的,而教科书是错的。孩子的
ac总是在waitpid()返回之前打印(exit(3)隐式调用fflush(2))。由于父级在waitpid之后打印c,因此ac不能在末尾。 -
bcac仅在您假设另一个孩子已经终止(显然不是这种情况,因为我们知道只有一个孩子被催生了!)或write调用由 @987654333 完成时才有可能@ 当 C 库在子退出时刷新其缓冲区时,在父进程中的printf完成write调用之后实现。这在理论上是可能的,但这是一种极其人为的假设诡辩。对于任何合理的想法,这是不可能的。 -
假设
printf()的代码将自己与一个线程关联,即父线程。现在父进程将运行,打印b,然后等待子进程。孩子将ac发送到printf()但printf()现在没有为孩子提供服务,因此孩子完成并且父母的c被打印。printf(),现在完成了父母的打印任务,转而为孩子服务并打印待处理的ac。所以,你得到bcac。请记住,printf()前面有 1 个或多个队列,除非每个printf()都附有fflush(),否则它们可能无法按打印顺序提供服务。cout包括fflush()。