Creating processes with fork and exec in Linux

1.0 fork and exec system calls

The use case is to execute a program in Linux environment. To execute a program, a process needs to be created. So, some process, already in existence, has to create a process for the program to be executed. In a typical command line scenario, the existing process is the shell. The shell creates a new process using the fork system call. The (earlier) existing process is the parent process and the newly created process is the child process.

The child process is a clone of the parent process. Its code, data and stack segments are a copy of the parent. There is a major difference, though. Since these are two different processes, their process ids are different. The return value of fork in parent and child are different. In the parent process, the return value of the fork system call is the process id of the child. In the child process, fork returns zero. Indeed, based on the return value of the fork system call, a process can decide whether it is the parent or the child and act accordingly.

What is the use of having a process which is a copy of its parent? Not much. But, then, the fork system call is to be used in conjunction with the exec system call. To be a little more precise, exec, actually, refers to a family of six system calls with names execl, execv, execlp, execvp, execle and execvpe. The differences between the six are rather fine and, in most cases, any one of the six forms can be used. We will use the family name exec to mean one of the exec system calls. The point is that, after fork, there are two processes, the parent and the child. In most cases, the child process, executes an exec system call to execute the program of interest. When the child process exec's a program, it initializes its code and the data segments with the program's code and data. The old code and data (of the copy of the parent) are overwritten with the new code and data of the program exec'ed.

Thus, we can conclude that fork and exec system calls are mostly used together. Without fork, exec is of very limited use and without exec, fork is hardly of any use.

2.0 An example

As an example, let's write two programs, parent and child. We will execute parent from the shell's command line. The parent would fork a child process and the latter would exec the child program in it. The parent would wait for the child to do its work and terminate.

2.1 Parent

// parent.c: the parent program #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/wait.h> int main (int argc, char **argv) { int i = 0; long sum; int pid; int status, ret; printf ("Parent: Hello, World!\n"); pid = fork (); if (pid == 0) { // I am the child execvp ("./child", NULL); } // I am the parent printf ("Parent: Waiting for Child to complete.\n"); if ((ret = waitpid (pid, &status, 0)) == -1) printf ("parent:error\n"); if (ret == pid) printf ("Parent: Child process waited for.\n"); }

2.2 Child

// child.c: the child program #include <stdio.h> #include <stdlib.h> #include <string.h> #define A 500 #define B 600 #define C 700 int main (int argc, char **argv) { int i, j; long sum; // Some arbitrary work done by the child printf ("Child: Hello, World!\n"); for (j = 0; j < 30; j++ ) { for (i =0; i < 900000; i++) { sum = A * i + B * i * i + C; sum %= 543; } } printf ("Child: Work completed!\n"); printf ("Child: Bye now.\n"); exit (0); }

2.3 Executing the parent (and child)

$ # compile parent $ gcc parent.c -o parent $ #compile child $ gcc child.c -o child $ # run parent (and child) $ ./parent Parent: Hello, World! Parent: Waiting for Child to complete. Child: Hello, World! Child: Work completed! Child: Bye now. Parent: Child process waited for. $

We took a rather simple example just to illustrate the concepts of parent and child programs and the respective processes. A more realistic example is the shell. The shell is the parent process. It reads each line of input from the command line, forks a child shell process, which in turn exec's the command. The shell parent process waits for the child to complete and then prompts for the next command.