考虑:
int main()
{
if (fork() == 0){
printf("a");
}
else{
printf("b");
waitpid(-1, NULL, 0);
}
printf("c");
exit(0);
}
(来自计算机系统,布莱恩特-奥哈拉隆)。
我们需要所有可能的输出序列。
我回答:acbc,abcc,bacc。
但是,与解决方案(bcac)相比,我缺少一个输出。我认为这个输出是不可能的,因为父进程在打印c(waitpid)之前等待其子进程返回。这不是真的吗?为什么?在这种情况下,上面的代码和没有waitpid行的代码有什么区别?
最佳答案
我不认为有任何可能。一开始,我以为会有一些诡计,因为stdio缓冲区会以意外的顺序刷新。但即便如此:
子项只有在输出bcac
之后才会输出c
。因此,a
中的第一个c
必须来自父代。
父级在完成bcac
之前不会输出c
。但这种情况只有在孩子完成后才能发生,包括在waitpid
期间发生的最后一次stdio刷新。因此,第一个exit()
总是来自孩子。
矛盾的证明已经实现了。。。输出不能小于cc>。
好吧,你可以做一件事来扰乱秩序。你可以在一个已经有一个即将退出的孩子的过程中执行这个程序。如果预先存在的孩子在新的孩子打印c
之前退出,那么主进程将检测到bcac
的退出,并继续打印它的东西,并在孩子打印任何东西之前退出。
这是在setuid程序中要注意的一点:不要假设因为您的程序只创建了一个子进程,所以它只有一个子进程。如果你在高级防御代码学习环境中,这个答案是有意义的。在unix新手环境中,这似乎并不相关,最好说a
是不可能的,尽管从技术上讲这不是真的。