我刚刚在C
制作了一个简单的演示程序,以了解fork()
的工作原理,并发现了一些我不了解的内容。在这个例子中:
void fork2()
{
printf("A");
fork();
printf("B");
}
输出为ABAB
,但在此示例中为:
void fork2()
{
printf("A\n");
fork();
printf("B\n");
}
输出为ABB
(当然是单独的行)。第二个是有道理的,因为如果我正确理解fork()
,它就会产生一个新的孩子,它在fork()
发生的地方之后开始(在这种情况下为printf("B\n");
)。我不明白的是,当我包含新的行字符时输出是不同的。
答案 0 :(得分:10)
printf()
缓冲输出,直到遇到换行符。因此,您的\n
- 更少版本将A
填充到输出缓冲区中,分叉。
由于两个进程相同(减去PID和诸如此类),它们现在都有一个包含A
的输出缓冲区。
继续执行并将B
打印到每个进程的缓冲区中。然后两个进程都退出,导致输出缓冲区刷新,两次打印AB
,每个进程一次。
你的另一个版本\n
会导致输出缓冲区在第一次printf()调用后刷新,而当fork命中时,两个进程都有一个空缓冲区。
答案 1 :(得分:1)
首先,不在您的代码中定义fork()
函数。 fork()
是已为您定义的系统调用。
您调用fork()
并且一旦(成功)返回,您有两个相同的进程执行fork()
调用之后的代码的下一行。在父进程中fork()
将返回子进程的PID;在子进程中,返回代码为0.根据此返回代码,您的两个进程可以根据其角色执行任何操作。
现在,对于这两个进程的相对执行顺序,无保证。众所周知,孩子可能不会在接下来的2分钟内执行,但这仍然是正确的行为。因此,这意味着您无法预期这些流程的两者的输出顺序是可预测的。
最后,将printf()
更改为fprintf()
以避免缓冲(在这种情况下会使事情进一步混淆)。