7.3.1 Starting A Child Process

7.3.1  Starting A Child Process

 A process, whether long-lived or short-lived, takes a certain amount of time. A process runs, does some computation, possibly changes the environment and usually returns, i.e., it finishes. Once the process is finished, it no longer exists. A process that is running can create one or more clones of itself. In the Unix environment, the only way to create a new process is by using the fork command. All Unix shells provide a fork command. Perl provides a counterpart with the same name. fork is usually called with no arguments.
It creates a process that is exactly similar to the one that created it.

The original process is called the parent process. The new process that is a clone is called a child process. Usually, a program is only one process that runs alone. However, after forking, the program is no longer one single process, but two processes running. In other words, the code following the fork is two processes running in parallel. These two processes need not be synchronized. They run at their own speed, and are independent of each other.

Thus, we need to distinguish between a program (or, a script) and a process. A program can have several processes running its code. A process, is in some sense, a thread of execution.

The following program forks a child process.

 Program 7.9

#!/usr/bin/perl

#fork a child process
fork ();

#Two processes running
print "After forking a child\n";

The program simply makes a call to fork. There is no argument given to fork. After fork() has been executed there are two processes running at the same time. Both processes execute the statements that follow the fork. Therefore, the statement

 

print "After forking a child\n";

 

is run two times, once by each independent process. The output of this program is given below.

After forking a child
After forking a child

To verify that there is only one process before the execution of fork(), and two afterwards, let us modify the program slightly and run it again. The modified program is given below.

 Program 7.10

#!/usr/bin/perl

print "Before forking a child\n";

fork ();

print "After forking a child\n";

The output of the program is given below.

Before forking a child
After forking a child
After forking a child

The print statement before the call to fork() is executed once, whereas the print statement afterwards is executed twice.

Of course, we can have more complex statements before and after the fork(). The following is another program that illustrates forking further.

 Program 7.11

#!/usr/bin/perl

my ($i, $j);

#Before forking
for ($i=0; $i <= 5; $i++){
print "\$i = $i\n";
}

fork ();

#After forking
for ($j=0; $j <= 4; $j++){
print "\$j = $j\n";
}

The output of the program is given below.

$i = 0
$i = 1
$i = 2
$i = 3
$i = 4
$i = 5
$j = 0
$j = 1
$j = 2
$j = 0
$j = 1
$j = 3
$j = 4
$j = 2
$j = 3
$j = 4

Here we see that the lines with the index $i are printed only once because before forking, there is only one process in the program. However, after forking, there are two processes: a parent process and a child process. The child process executes the for loop with index $j once, and the parent process executes the loop another time. The two processes share the variable name
$j, but keep two separate copies of it. Also, the two processes run in parallel without any synchronization. Therefore, the lines printed by the two processes can occur in any sequence.

 We can fork as many processes as we want although it may not be a great idea if the processes are not doing anything useful. But, for the purpose of illustration, let us look at the next program.

 Program 7.12

#!/usr/bin/perl

my ($i, $j);

#fork 7 child processes
for ($i=0; $i <= 2; $i++){
    fork ();
}

#The for loop is executed four times by four  different processes
for ($j=0; $j <= 2; $j++){
    print "\$j = $j\n";
}

Here, the first for loop forks seven processes leading to a total of eight processes when the loop is fully executed. This happens in the following manner.

Before the loop starts, there is only one process in the program. The execution of the first run of the loop for $i = 0, forks a child process. Therefore, before the second run of the loop, we have two processes. Now, the second run of the loop causes each one of the two processes to produce two new children, leading to 4 processes overall. The third and the final run of the loop produces four more children, causing a total of eight processes to exist at the same time. That is why the second loop is executed 8 times. Each process executes the second for loop independently. The eight processes run independently without any synchronization. The parent for each child process is the original process that existed in the beginning of the program.

A sample output of this program is given below.

$j = 0
$j = 0
$j = 0
$j = 0
$j = 0
$j = 0
$j = 1
$j = 2
$j = 1
$j = 2
$j = 1
$j = 2
$j = 0
$j = 1
$j = 2
$j = 1
$j = 2
$j = 0
$j = 1
$j = 2
$j = 1
$j = 2
$j = 1
$j = 2

The output is quite likely to vary from one run to another.

Finally, we write a small program that has several fork statements, one after the other. These statements are not included in a loop like in the previous program.

 Program 7.13

#!/usr/bin/perl

print "Before forking\n";
fork (); #1st forking
print "After first forking\n";
fork (); #2nd forking
print "After second forking\n";
fork();  #3rd forking
print "After third forking\n";
sleep 1;

The program has only one process to start with. Then, it forks a process. Therefore, after the first fork, we have two processes—the original process and a child process. Therefore, the line

 

After first forking

 

is printed twice. Next, we call fork() a second time. Each of the two processes creates two children. Therefore, the line

 

After second forking

 

is printed four times. The last line is printed eight times. A sample output from running the program is given below.

Before forking
After first forking
After second forking
After third forking
After first forking
After second forking
After second forking
After third forking
After second forking
After third forking
After third forking
After third forking
After third forking
After third forking
After third forking

We see that the lines can be printed in an arbitrary order depending on how the processes run. The output will vary from one run to another. We put the sleep command at the end to make the output printed look nice. Otherwise, the Unix prompt may be printed after any one of the processes has finished printing the last line. This statement causes each of the eight processes to wait a second after the last line is printed. During this time, all the other processes also print their output.