How forking twice avoids zombie? Understanding the concept!

Spread the love

First of all, what is a process?

A program in execution is called as a process.

When a process is created using fork() command it’s information is added to the process table. The kernel track the created and running process using the process descriptor. When the process ends, its information is removed from process table by the parent process.

Zombie Process: When a process die and it’s information is not removed from process table by parent process then it becomes a zombie. It does not use any other resource of the system, just it’s entry is wasting space in the process table. If it is less in number then not a big issue but what if it is more? Simply wasting space in the process table.

How a process becomes a zombie (defunct)?

When a process completes its execution and wants to terminate then it sends exit() signal to its parent. When the parent receives exit()) signal then it removes its information from the process table. But sometimes the child process runs for a very long time and the parent can’t wait for that long so it continues doing its work and hence do not respond to child exit() status and hence do not remove its information from the process table. Then that dead child process becomes a zombie process. It is denoted by Z.

How to avoid zombie process?

Zombie process can be avoided by following ways.

  1. Make parent wait until the child finishes its execution using wait() or waitpid(). So that it can collect exit() status and removes its information from the process table.
  2. The parent process can register a SIGCHLD handler with signal(). The child process will give a SIGCHLD signal after it exits, and parent can recover child in the handler.
  3. If the parent doesn’t care when the child exits, it can notice kernel by signal(SIGCHLD, SI_IGN). Then kernel will recover defunct child and parent process will not receive the SIGCHLD signal.
  4. By forking twice!

Analyzing the solutions

It always depends on the programmer what they choose, this is just my opinion!

  1. Let for example the child executes for 2 hours and the parent is made to wait for it. Isn’t it parent process capability is wasted? It’s just sitting and doing nothing, just waiting for the child execution completion.
  2. Registering SIGCHLD handler is not easy and makes the code more big and complex.
  3. Same as above.
  4. The last one and the most popular one is by forking twice. We will understand it using some examples.
READ  How to set up FreeGLUT and GLEW in Microsoft Visual Studio

Example:

A programmer wrote a program to do some work and in the program, he has to calculate the sum of the numbers from 0 to 10000. Let the whole program will take 2 hours to complete and only calculating sum will take 1 hour. What he do is, he creates a child in his program which will calculate the sum.

If a child is created and it is calculating the sum for 1 hour, the parent will not be waiting so long so it will do other work of that program. Upon completion of calculation when it want to terminate then it will send exit() signal to its parent but the parent will not receive it because it is busy doing another work hence it will not remove child process entry from the process entry table so the dead child process will become a zombie.

To prevent it if programmer direct parent to wait until the child completes using wait() command then it is wasting capability of the parent process and since it is waiting for 1 hour and doing nothing so the whole program will be completed in 3 hours.

Now, How forking twice avoids zombie?

Parent A will create a child say B, Child B will then create another child under it say C. Now, B is the child of parent A and C is the child of B. So C is the grandchild of parent A. Parent A is made to wait for its child completion. So it will wait for child B completion. Calculation of sum is assigned to grandchild process C. And then child B terminates!

Since parent A was waiting for its child completion so will receive child B exit() status and removes its entry from the process table. Parent A didn’t wait too long as he created a child B, B further created another child C, assigned sum calculation work to it and then child B terminated.

READ  Viral : An inspiring ad by Surf Excel - Ramadan 2016

Child B work is to fork() another child, assigned calculation work and then terminate. It will not take more than a second in the real world and hence parent A didn’t wait for more than a second and again started doing its work. Meanwhile, child C is calculating the sum for 1 hour. Since child C parent(process B) has died it will become orphan process and hence, all such process whose parent has died is adopted by init, the main process of the OS having process id = 1. And init will wait for its child completion and removes the entry from process table once they complete.

So after 1-hour child C sends exit() signal to its parent(now init) which will then removes its entry from process table so the child C do not become a zombie. Child B is already terminated and is not a zombie as its entry was removed from process table by Parent A. Meanwhile parent A was doing other work of that program while child C was calculating the sum.

In this way, our goal is achieved, also, we didn’t make parent A to wait for so long to avoid a zombie. We used forking twice to avoid zombie!

To view running process in Unix system ps command is used.

Below it C program to avoid zombie by forking twice.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
    int pid;
    pid = fork();
    if (pid < 0)
    {
        printf("Fork Failed");
        exit(0);
    }
    if (pid == 0)
    {
        // First child
        pid = fork();
        if (pid == 0) 
        {
            // Second child
            sleep(1);
            printf("Second child: My parent PID is %d\n", getppid());
        }
    }
    else 
    {
        // Parent process
        wait(NULL);
        sleep(2);
        system("ps -o pid,ppid,state,tty,command");
    }
    return 0;
}

Output:

zombie-avoided

If we will remove wait() from the above program then parent A will not wait for child B completion and hence not remove it’s entry from the process table. Then the process will become a zombie. It is denoted by Z.

Output of above program without wait()

zombie-process

 


Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.