fork() branches more than expected?

2019-01-03 07:58发布

Consider the following piece of code:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    int i;
    for(i = 0; i < 2; i++)
    {
        fork();
        printf(".");
    }
    return 0;
}

This program outputs 8 dots. How can that be possible? Should not there be 6 dots instead?

标签: c++ c fork
3条回答
smile是对你的礼貌
2楼-- · 2019-01-03 08:53

You have uncommitted buffers in the output streams. stdout is line-buffered, and the buffer is replicated together with the rest of the process. When the program terminates, the uncommitted buffer is written twice (once for each process). Both using

printf("a\n");

and

printf("a "); fflush(stdout);

don't exhibit the problem.

In your first example, you create four processes which have each two dots in their output stream buffer. When each stream terminates, it flushes its buffer, generating eight dots.

查看更多
时光不老,我们不散
3楼-- · 2019-01-03 08:53

when i=0

Process_1: Buffered text= 1 dot

Process_2(created by Process_1): Buffered text= 1 dot

when i=1

Process_3(created by Process_1): Inherit 1 buffered dot from Process_1 and prints 1 dot by itself. In total Process_3 prints 2 dots.

Process_4(created by Process_2): Inherit 1 buffered dot from Process_2 and prints 1 dot by itself. In total Process_4 prints 2 dots.

Process_1 : Prints 2 dots (One buffered dot when i=0 and another dot when i=1)

Process_2 : Prints 2 dots (One buffered dot when i=0 and another dot when i=1)

Final Output: 8 dots. :)

查看更多
混吃等死
4楼-- · 2019-01-03 08:58

The fork() primitive often stretches the imagination. Until you get a feel for it, you should trace out on paper what each operation is and account for the number of processes. Don't forget that fork() creates a near-perfect copy of the current process. The most significant difference (for most purposes) is that fork()'s return value differs between parent and child. (Since this code ignores the return value, it makes no difference.)

So, at first, there is one process. That creates a second process, both of which print a dot and loop. On their second iteration, each creates another copy, so there are four processes print a dot, and then exit. So we can easily account for six dots, like you expect.

However, what printf() really does is buffer its output. So the first dot from when there were only two processes does not appear when written. Those dots remain in the buffer—which is duplicated at fork(). It is not until the process is about to exit that the buffered dot appears. Four processes printing a buffered dot, plus the new one gives 8 dots.

If you wanted to avoid that behavior, call fflush(stdout); after printf().

查看更多
登录 后发表回答