User Tools

Site Tools


cs:system_calls:fork_and_processes
Return to Home page

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
/web/htdocs/www.skenz.it/home/data/pages/cs/system_calls/fork_and_processes.txt · Last modified: 2024/04/08 22:35 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki
Privacy Policy