Visually what happens to fork() in a For Loop

lucidgold picture lucidgold · Nov 7, 2014 · Viewed 50.5k times · Source

I have been trying to understand fork() behavior. This time in a for-loop. Observe the following code:

#include <stdio.h>

void main()
{
   int i;

   for (i=0;i<3;i++)
   {
      fork();

      // This printf statement is for debugging purposes
      // getppid(): gets the parent process-id
      // getpid(): get child process-id

      printf("[%d] [%d] i=%d\n", getppid(), getpid(), i);
   }

   printf("[%d] [%d] hi\n", getppid(), getpid());
}

Here is the output:

[6909][6936] i=0
[6909][6936] i=1
[6936][6938] i=1
[6909][6936] i=2
[6909][6936] hi
[6936][6938] i=2
[6936][6938] hi
[6938][6940] i=2
[6938][6940] hi
[1][6937] i=0
[1][6939] i=2
[1][6939] hi
[1][6937] i=1
[6937][6941] i=1
[1][6937] i=2
[1][6937] hi
[6937][6941] i=2
[6937][6941] hi
[6937][6942] i=2
[6937][6942] hi
[1][6943] i=2
[1][6943] hi

I am a very visual person, and so the only way for me to truly understand things is by diagramming. My instructor said there would be 8 hi statements. I wrote and ran the code, and indeed there were 8 hi statements. But I really didn’t understand it. So I drew the following diagram:

enter image description here

Diagram updated to reflect comments :)

Observations:

  1. Parent process (main) must iterate the loop 3 times. Then printf is called
  2. On each iteration of parent for-loop a fork() is called
  3. After each fork() call, i is incremented, and so every child starts a for-loop from i before it is incremented
  4. At the end of each for-loop, "hi" is printed

Here are my questions:

  • Is my diagram correct?
  • Why are there two instances of i=0 in the output?
  • What value of i is carried over to each child after the fork()? If the same value of i is carried over, then when does the "forking" stop?
  • Is it always the case that 2^n - 1 would be a way to count the number of children that are forked? So, here n=3, which means 2^3 - 1 = 8 - 1 = 7 children, which is correct?

Answer

Crowman picture Crowman · Nov 7, 2014

Here's how to understand it, starting at the for loop.

  1. Loop starts in parent, i == 0

  2. Parent fork()s, creating child 1.

  3. You now have two processes. Both print i=0.

  4. Loop restarts in both processes, now i == 1.

  5. Parent and child 1 fork(), creating children 2 and 3.

  6. You now have four processes. All four print i=1.

  7. Loop restarts in all four processes, now i == 2.

  8. Parent and children 1 through 3 all fork(), creating children 4 through 7.

  9. You now have eight processes. All eight print i=2.

  10. Loop restarts in all eight processes, now i == 3.

  11. Loop terminates in all eight processes, as i < 3 is no longer true.

  12. All eight processes print hi.

  13. All eight processes terminate.

So you get 0 printed two times, 1 printed four times, 2 printed 8 times, and hi printed 8 times.