fork() and "\n"

3

我刚刚用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");)。我不理解的是,为什么在包含换行符时输出结果会不同。
2个回答

11

printf()函数会缓存输出,直到遇到换行符。因此你的没有\n版本将A塞入输出缓冲区并分叉。

由于这两个进程是相同的(除了PID等),它们现在都有一个包含A的输出缓冲区。

执行继续,并在每个进程的缓冲区中打印B。然后两个进程都退出,导致输出缓冲区刷新,每个进程都打印出AB两次。

你的另一个版本,则带有\n,在第一次printf()调用后导致输出缓冲区刷新,当分叉命中时,两个进程都有一个空缓冲区。


非常好的解释,谢谢。 - cHam

1
首先,不要在您的代码中定义fork()函数。 fork()是一个已为您定义的系统调用
您调用fork(),一旦它(成功)返回,您就有两个相同的进程执行fork()调用后的下一行代码。在父进程中,fork()将返回子进程的PID;在子进程中,返回值为0。基于此返回代码,您的两个进程可以根据其角色执行其打算执行的任何操作。
现在,这两个进程的执行顺序没有保证。您所知道的是,子进程可能不会执行接下来的2分钟,但这仍然是正确的行为。因此,这意味着您不能期望从这两个进程的输出顺序是可预测的。
最后,请将printf()更改为fprintf()以避免缓冲(在这种情况下会使事情更加混乱)。

我实际上称它为fork2(),但删除了这里的2,因为我认为这样更容易阅读。不过你说的有道理,所以我现在会改回去。 - cHam
1
这个“答案”并没有回答这个问题。该问题主要是关于为什么在第一种情况下“A”被打印了两次(而在第二种情况下只打印了一次),而不是有关打印顺序的问题。 - Eric Postpischil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接