cleo
cleo

Reputation: 165

I don't understand this example of fork()

I have this example of code, but I don't understand why this code creates 5 processes plus the original. (6 process total)

#include <unistd.h>

int main(void) {
    int i;
    for (i = 0; i < 3; i++) {
        if (fork() && (i == 1)) {
            break;
        }
    }
}

Process graph

Upvotes: 14

Views: 5982

Answers (7)

joctee
joctee

Reputation: 2479

If your main process have pid A, and B - F are subprocesses pids, then:

A    spawns  B          i=0
A    spawns  C          i=1
C    run from 'fork'    i=1
C    spawns  D          i=2
B    run from 'fork'    i=0
B    spawns  E          i=1
D    run from 'fork'    i=2
E    run from 'fork'    i=1
E    spawns  F          i=2
F    run from 'fork'    i=2

Where i is the value of i of the (sub)process' context. Since fork creates an exact copy of the running process, the variable i will also be copied. When A spawns B, i is 0. When A spawns C, i is 1 . Process A now exits the for-loop since i == 1.

Now, subprocess C starts to run, with i == 1. Note that it will not break inside the for-loop since fork(), at C's spawning point, returns 0. Instead it will loop, increasing i to 2, spawn D, and exit because of the for-loop's condition.

The subprocess B have i == 0, when it starts. It spawn subprocess E, and breaks inside the for-loop. (i == 1)

And so on...

When you are tyring to find out of thing like these, I can give you an advice:

Make intermediate variables and print them.

I modified your code, so that it prints out the things I just described:

#include <unistd.h>
#include <stdio.h>

int main(void) {
    int i;
    for (i= 0; i < 3; ++i) {
        int f = fork();
        printf("%i\tspawns\t%i\ti=%i\n", getpid(), f, i);
        if (f && (i == 1))
            break;
    }

    getchar();
}

Upvotes: 12

Aidan Brumsickle
Aidan Brumsickle

Reputation: 659

In the parent process, fork() returns the PID of the child process, and in the child process, it returns 0. With this in mind, look at each iteration of the for loop: (Let's say for simplicity's sake that the PID of the original process is 1)

  1. i == 0
    • Process 1: i == 0, fork returns PID of child process (say 2) (2 != 0), true && false == false, so we don't break.
    • Process 2: i = 0, fork returns 0, false && false == false, so we don't break.
  2. i == 1
    • Process 1: i == 1, fork returns PID of child process (say 3), true && true == true, so break.
    • Process 2: i == 1, fork returns PID of child process (say 4), true && true == true, so break.
    • Process 3: i == 1, fork returns 0, false && true == false, so don't break.
    • Process 4: i == 1, fork returns 0, false && true == false, so don't break.
  3. i == 2
    • Process 1 is out of the loop.
    • Process 2 is out of the loop.
    • Process 3: i == 2, fork returns PID of child process (say 5), true && false == false, so don't break
    • Process 4: i == 2, fork returns PID of child process (say 6), true && false == false, so don't break
    • Process 5: i == 2, fork returns 0, false && false == false, so don't break
    • Process 6: i == 2, fork returns 0, false && false == false, so don't break
  4. i == 3 so done with loop.

Upvotes: 6

Timothy Jones
Timothy Jones

Reputation: 22125

fork() splits a process in two, and returns either 0 (if this process is the child), or the PID of the child (if this process is the parent). So, this line:

if (fork() && (i == 1)) break;

Says "if this is the parent process, and this is the second time through the loop, break out of the loop". This means the loop runs like this:

  • i == 0: The first time through the loop, i is 0, we create two processes, both entering the loop at i == 1. Total now two processes

  • i == 1: Both of those processes fork, but two of them do not continue to iterate because of the if (fork() && (i == 1)) break; line (the two that don't continue are both of the parents in the fork calls). Total now four processes, but only two of those are continuing to loop.

  • i == 2: Now, the two that continue the loop both fork, resulting in 6 processes.

  • i == 3: All 6 processes exit the loop (since i < 3 == false , there is no more looping)

Upvotes: 30

rasmus
rasmus

Reputation: 3216

First we have one process. Consider the iterations of the loop:

i = 0

The first process calls fork. Now we have 2 processes.

i = 1

The two processes calls fork. Now we have 4.

Fork returns 0 in the newly created processes: Two processes will break from the loop and two will continue in the loop.

i = 2

The two remaining processes calls fork. We get 2 new processes (totaling 6).

Upvotes: 3

Karoly Horvath
Karoly Horvath

Reputation: 96258

I can count six processes (X) here:

i=0          fork()
            /      \
i=1   fork()        fork()
      /    \>0       /   \>0
      |    X break   |   X break
i=2 fork()       fork()
     / \          /  \
    X  X         X    X

Upvotes: 5

asaelr
asaelr

Reputation: 5456

the loop run from i==0 to i==2.

In the first iterate, the original process (p0) create another one (p1)

In the second iterate, p0 and p1 create one new process each (p2 and p3), and break (Since i==1 and fork return a non-zero value to the father).

In the third iterate, p2 and p3 create one new process each (p4 and p5).

So, at last, you got 5 new processes.

Upvotes: 3

mikithskegg
mikithskegg

Reputation: 816

In the children processes the cycle continues to iterate. So they produce new processes too.

Upvotes: 2

Related Questions