Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I don't understand this example of fork()

Tags:

c

fork

unix

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

like image 327
cleo Avatar asked Feb 12 '12 22:02

cleo


People also ask

What is fork () used for?

fork() in C. Fork system call is used for creating a new process, which is called child process, which runs concurrently with the process that makes the fork() call (parent process). After a new child process is created, both processes will execute the next instruction following the fork() system call.

What does fork () do in Linux?

fork() creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process. The child process and the parent process run in separate memory spaces.

What is the value of fork ()?

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.

What does PID fork () mean?

pid_t fork(void); Description: fork creates a child process that differs from the parent process only in its PID and PPID, and i. Page 1. pid_t fork(void); Description: fork creates a child process that differs from the parent process only in its PID and PPID, and in the fact that resource utilizations are set to 0.


2 Answers

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)

like image 123
Timothy Jones Avatar answered Sep 16 '22 16:09

Timothy Jones


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();
}
like image 40
joctee Avatar answered Sep 19 '22 16:09

joctee