Understanding Zombie Process


Introduction to Zombie (Defunct) Processes:-

The term ‘Zombie Process’ comes from the literal definition of the word zombie, which refers to an undead person. In operating systems like Unix, etcetera, zombie processes or defunct processes may be defined as those processes which have completed their execution by issuing the exit() system call but whose Process Control Block (PCB) is still in the Process Table of the system. Before getting removed from the Process Table, every process reaches a state known as the ‘Terminated State’ and it is in this state that a process is known as a zombie process.

Now the question arises why do these zombie processes exist? The answer to this question is that these zombie processes are nothing but child processes that wait for their respective parent process to read their exit() system call using the wait() system call. Once the exit system call of these zombie processes is read, the entries of the zombie processes in the Process Table are removed and they are said to be “reaped” by the parent process.

Under normal scenarios, zombie processes are immediately waited by their respective parent processes and then, reaped by the system. But what if these processes are not waited by their respective parent processes? This usually happens when an error has occurred and it usually results in a resource leakage. Because of this, the zombie entries in the operating system will continue to exist infinitely. But since the only resource that these zombie processes occupy is the Process Entry Table, the damage done is not a lot. Also, a special process of operating systems, known as the ‘Reaper Process’, runs periodically and recovers any such zombie process states present in the Operating System.

An interesting thing to note about Zombie Processes is that the kill command has no effect on these zombie processes. As we can see, zombie processes have lots of interesting properties (we are going to learn more about them in the latter part of this article) and that is why a lot of interviewers of huge software companies ask questions on these (find more interview questions on operating systems at this site) processes to assess how well the candidates for the job know about operating systems. Hence, to get a good understanding of operating systems, one should definitely study Zombie Processes.

Illustration of Zombie Processes using an example:-

Now, let us take a look at an example in order to understand Zombie Processes in details:-

Code Snippet :-(Coding Language used - C)

/* This program in the C language aims at demonstrating Zombie Processes.*/

//including the necessary header files
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

//main function of the C Program
int main()
{
    /* The fork() system call forks a parent process (in this case, the default process)   to create a child process. It returns either zero or the process id of the newly created child process.*/

    pid_t childProcessId = fork();

    /* If the value of childProcessId is greater than zero, it means that fork() has  returned to the parent process with the id of the newly created child process. */

if (childProcessId > 0){
sleep(100);
}

    /* If the value of childProcessId is equal to zero, it means that fork() has returned to the newly created child process. */

              else{     
        exit(0);
              }

    /*In this code, the child process becomes a Zombie Process as the parent process is still sleeping when the child process has issued the exit system call.  */

    return 0;
}
//end of main function

Explanation of the Code Snippet:-

In the code snippet given above, we can see that firstly, a child process is forked from the default parent process using the fork() system call. If the processor enters the parent process (the condition is: childProcessId > 0), the parent process is made to sleep for a time period of hundred seconds. On the other hand, if the child process is being currently executed, the child process issues an exit() system call immediately. But as the parent process is not waiting (as it is sleeping), the child process will not be reaped immediately. Hence the child process becomes a Zombie Process after termination. All the resources used by the child process except for its Process Control Block (PCB) will be released when it becomes a Zombie Process. After the duration of sleep of the parent process, that is, 100 seconds, is over, the parent process will issue the wait() system call and the zombie child process will be reaped.

NOTE: The fork() system call is usually disabled in online compilers. So in order to use the above code, one has to run it on his/her local machine.

Dealing with Zombie Process:-

As we have already seen, if the Zombie Processes exist for a long period of time, the Process Table would get filled up really fast. Usually, each system has only a single Process Table and that too, with a finite size. Hence, if too many zombie processes are created, the Process Table will be almost full and the system will not be able to generate any new process in the future. This might lead the system to a standstill. Therefore, we need ways to prevent the creation of zombie processes.

Let us take a look at a few ways to prevent the creation of Zombie Processes:-

  • Killing the Parent Process of the Child Process: One of the simplest ways of preventing the creation of zombie processes is to kill the parent process of the child process. In this way, the child process would become an orphan (we will learn about the difference between orphan processes and zombie processes later in this article) and would be reparented in the future. Thus, a Zombie Process would never be created. However, it is not usually possible to kill the parent process, and therefore, although theoretically, this idea might work to prevent the creation of zombie processes, it is not as feasible practically.
  • By the usage of the wait() system call: When a child process is forked from a parent process and the parent processes issues a wait() system call, it means that the parent process will wait for the complete execution of the child process, that is, the parent process will wait for the child process to issue the exit() system call before it executes any further. The execution of the parent process gets suspended temporarily as it waits in the waiting queue. Hence, after the termination of the child process’s execution, it will definitely be reaped by the parent process and hence, Zombie Process will not be created for long. The following code snippet illustrates the usage of the wait() system call to prevent the creation of Zombie Processes:-
(Coding Language used - C)
//including the necessary header files
#include<stdio.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>

//main function of the C Program
int main()
{

    pid_t childProcessId = fork();
    //child process forked from the parent process.

    if (childProcessId == 0)
    {
        //Child Process Block
int j; 
        for (j = 0; j < 10;  j ++)
            printf(" Child Process\n");
    }
    else
    {
        //Parent Process Block
        wait(NULL);
//Parent process waits for child process to finish its execution
        printf("Parent Process\n");
        while(1);
    }
return 0;
}
//end of main function
  • By Ignoring the SIGCHLD signal of the Child Process: When a child process reaches its terminated state, a signal “SIGCHLD” is sent to its parent process to inform it about the termination of the child process. The parent process then takes further actions to reap the child’s process. However, if we ignore the SIGCHLD signal by calling the signal function as signal(SIGCHLD, SIG_IGN), then the child process entry is deleted from the process table and thus, the creation of a zombie process is avoided. However, in this case, the parent process would not know about the exit status of the child. The following code snippet illustrates this idea:-

(Coding Language used - C)


//including the necessary header files
#include<stdio.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>

//main function of the C Program
int main()
{
pid_t childProcessId = fork();
    //child process forked from the parent process.

    if (childProcessId == 0)
    {
        //Child Process Block
int j; 
        for (j = 0; j < 10;  j ++)
            printf(" Child Process\n");
    }
    else
    {
        //Parent Process Block
        signal(SIGCHLD,SIG_IGN);
/*The SIGCHLD signal is ignored by the system and the entry of the child process in the process table is removed.*/
        printf("Parent Process\n");
        while(1);
    }
return 0;
}
//end of main function
  • By the usage of a Signal Handler: When the SIGCHLD signal is issued and reaches the parent process, the parent process creates what is known as a signal handler for the signal, which in turn, calls the wait() system call inside itself. Hence, the parent process collects the exit status of the child process immediately and the entry of the child process in the Process Table is removed. Thus, the child process is reaped immediately and no defunct process is created. The code snippet given below implements this idea to avoid the creation of zombie processes:-

(Coding Language used - C)

//including the necessary header files
#include<stdio.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>

    // This function calls the wait() system call
void waitFunctionCaller(int signum)
{
    wait(NULL);
}

//main function of the C Program
int main()
{
    pid_t childProcessId = fork();
    //child process forked from the parent process.

    if (childProcessId == 0)
    {
        //Child Process Block
int j; 
        for (j = 0; j < 10;  j ++)
            printf(" Child Process\n");
    }
    else
    {
        //Parent Process Block
        signal(SIGCHLD,waitFunctionCaller);
/*When the SIGCHLD signal is received by the parent process,it calls the function waitFunctionCaller.*/
        printf("Parent Process\n");
        while(1);
    }
return 0;
}
//end of main function

Side effects of Zombie Processes:-

As mentioned earlier in this article, the creation of a lot of zombie processes might lead to the filling up of the Process Table of the system. Let us consider the following scenario :-

(Coding Language used - C)

//including the necessary header files
#include<stdio.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>

//main function of the C Program
int main()
{
    while(1) 
{
fork();    
    }
return 0;
}
//end of main function

In this scenario, an infinite number of zombie processes are created as the parent process (default process here) is not waiting for the child process. The number of process ids in an operating system is limited and all of them will be soon taken up by the zombie processes, due to which no more processes can be created and one’s system will crash.

Hence, it is pretty evident that if such scenarios occur, zombie processes can prove to be lethal and a lot of resource leakage will occur. Hence, it is better to avoid the creation of a lot of Zombie Processes in the first place.

Zombie Processes V/S Orphan Processes:-

Zombie processes are not the same as orphan processes. As the name suggests, Orphan processes are those child processes whose parent processes have already finished their execution without waiting for their child processes to complete their execution. Let us take a look at a code snippet to understand what orphan processes are:-

(Coding Language used - C)

// including all the necessary header files
#include<stdio.h>
#include <unistd.h>
#include<sys/wait.h>    
#include <sys/types.h>

//main function of the C program
int main()
{
    pid_t processId = fork();

if(processId == 0) {
    // Child Process block
    sleep(100);
 }
else if (processId > 0) {
// Parent Process block
exit(0); 
/* Parent process terminates before the child process making it an orphan         process*/
}

 return 0;
}
//end of main function

As we can see in the above code snippet, as soon as the control reaches the parent process, it terminates without even waiting for the child process to terminate, thus leading to the creation of an orphan process.

As soon as a process becomes an orphan process, it is reparented, that is, another process becomes its new parent (usually the INIT process is the new parent process).

So, now we understand how the zombie processes and orphan processes are different from each other.

Conclusion:-

In this article, we learned a lot about Defunct processes and Orphan Processes. We also took a look at code snippets to understand how these processes are created and how the operating system handles them. A good understanding of Zombie Processes and Orphan Processes is crucial for those people who want to study operating systems and we hope that through this article, we have been able to make the concepts of Zombie and Orphan processes clear for our readers.

#operating system #os #system admin #programmer #software engineering #zombie process #Coding






你可能感興趣的文章

[day-11] JS 陣列 forEach 資料處理方法

[day-11] JS 陣列 forEach 資料處理方法

HTML 起手式

HTML 起手式

Vue-Admin-Template 之 request.js code搞怪

Vue-Admin-Template 之 request.js code搞怪






留言討論