Fork and processes generation (System Calls: ''fork'')
Concepts:
Use of the system call fork
to generate a number of processes.
Text:
Realize a program that receives from command line two integer numbers, n_levels
and n_children
.
The program (father process) must create a number of children equal to n_children
and terminate.
In turn, every child must generate n_children
children and terminate.
This process must be repeated n_levels
times (at the end (n_children)^(n_levels) leaves processes are in execution).
Such processes (the “leaves” processes) must wait 1 second, and then print (into the screen) a termination message.
Solution:
- fork_and_processes.c
/* Realize a program that receives from command line two integer numbers, n_levels and n_children. The program (father process) must create a number of children equal to n_children and terminate. In turn, every child must generate n_children children and terminate. This process must be repeated n_levels times (in that moment (n_children)^(n_levels) leaves processes are in execution. Such processes (the "leaves" processes) must wait 1 second, and then print (into the screen) a termination message. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { pid_t pid; int i, j; int n_levels = atoi(argv[1]); int n_children = atoi(argv[2]); fprintf(stdout, "FIRST PROCESS: PID %d PPID: %d\n", getpid(), getppid()); for (i=0; i<n_levels; i++) { for(j=0; j<n_children; j++) { pid = fork(); if (pid == 0) { /* Child */ fprintf(stdout, "PID %d PPID %d\n", getpid(), getppid()); break; /* The child exits from the inner loop */ } } if(pid!=0){ /* Father */ sleep(2); /* In order to leave active the father processes when "leaves" processes terminate their execution. It is useful in order to not have zombies processes when the last fprintf of this program is executed. In this case the getppid() function prints the pid of the real father and not the one of the process init/upstart */ exit(0); /* After the generation of n_children children the father ends */ } } sleep(1); fprintf(stdout, "LEAVES: PID %d PPID %d\n", getpid(), getppid()); return (0); }
Output:
The output of the program with n_levels=2
and n_children=3
is:
$ ./prog 2 3 FIRST PROCESS: PID 2839 PPID: 1616 PID 2840 PPID 2839 PID 2842 PPID 2839 PID 2841 PPID 2839 PID 2845 PPID 2841 PID 2844 PPID 2842 PID 2846 PPID 2842 PID 2847 PPID 2841 PID 2849 PPID 2840 PID 2843 PPID 2842 PID 2850 PPID 2840 PID 2848 PPID 2841 PID 2851 PPID 2840 LEAVES: PID 2845 PPID 2841 LEAVES: PID 2844 PPID 2842 LEAVES: PID 2846 PPID 2842 LEAVES: PID 2847 PPID 2841 LEAVES: PID 2849 PPID 2840 LEAVES: PID 2843 PPID 2842 LEAVES: PID 2850 PPID 2840 LEAVES: PID 2848 PPID 2841 LEAVES: PID 2851 PPID 2840
Note that the actual values of the pids change for every execution of the program.
Comments
The most complex part of this program is the code inside the more external for
cycle (executed n_levels
times):
for(j=0; j<n_children; j++) { pid = fork(); if (pid == 0) { /* Child */ break; } } if(pid!=0){ /* Father */ exit(0); /* After the generation of n_children children the father ends */ }
This code generates n_children
child processes and then it ends the execution of the father process.
The father executes n_children
forks generating n_children
children processes, then it exits the cycle, since the variable pid
, in the case of the father, contains a value different from 0 (the system call fork
returns to the father the pid of the generated child). To terminate its execution, the father call the system call exit
.
Each child executes the instruction break
to exit from the for cycle. Otherwise, each child would generating other processes by executing other times the system call fork
.
Remember that the break
instruction can be substituted with a variable (flag
) that involves the exit from the for cycle for the child generated by the system call fork
:
flag = 1; for(j=0; j<n_children && flag; j++) { pid = fork(); if (pid == 0) { /* Child */ flag = 0; } } if(pid!=0){ /* Father */ exit(0); /* After the generation of n_children children the father ends */ }
Control flow chart (CFG):
Assuming n_levels=2
and n_children=3
, the control flow chart is:
Processes generation tree:
Assuming n_levels=2
and n_children=3
, the processes generation tree is:
If you found any error, or if you want to partecipate to the editing of this wiki, please contact: admin [at] skenz.it
You can reuse, distribute or modify the content of this page, but you must cite in any document (or webpage) this url: https://www.skenz.it/cs/system_calls/fork_and_processes