Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visually what happens to fork() in a For Loop

Tags:

c

fork

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?
like image 315
lucidgold Avatar asked Nov 07 '14 03:11

lucidgold


People also ask

What happens when fork is executed?

When the main program executes fork(), an identical copy of its address space, including the program and all data, is created. System call fork() returns the child process ID to the parent and returns 0 to the child process.

What is fork () used for?

In the computing field, fork() is the primary method of process creation on Unix-like operating systems. This function creates a new copy called the child out of the original process, that is called the parent. When the parent process closes or crashes for some reason, it also kills the child process.

How many processes are created by fork in for loop?

So there are total eight processes (new child processes and one original process).

What does the fork () return to the child process?

RETURN VALUE Upon successful completion, fork() returns 0 to the child process and returns the process ID of the child process to the parent process. Otherwise, -1 is returned to the parent process, no child process is created, and errno is set to indicate the error.


2 Answers

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.

like image 97
Crowman Avatar answered Oct 07 '22 18:10

Crowman


  1. Yes, it's correct. (see below)
  2. No, i++ is executed after the call of fork, because that's the way the for loop works.
  3. If all goes successfully, yes. However, remember that fork may fail.

A little explanation on the second one:

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

is similar to:

i = 0; while (i < 3) {     fork();     i++; } 

So i in the forked processes(both parent and child) is the value before increment. However, the increment is executed immediately after fork(), so in my opinion, the diagram could be treat as correct.

like image 26
Yu Hao Avatar answered Oct 07 '22 18:10

Yu Hao