How to deep understand the Zombie Process in linux?

A process to end his own life when invoking the exit command, but it is not really be destroyed, but leave a called zombie process (Zombie)data structure (the exit system call, it is just can exit the process and let a normal process become a zombie process, and that process can not be completely destroyed).zombie

What is a Zombie Process?

When each process end, the kernel will release all of resources, including the open file, memory. However, the process still retain some certain informations (including the process ID, the termination status of process, CPU running time ), until the parent process remove it by executing the wait/waitpid system call. Now this process is dead state, the process is to be a zombie (Zombie Process). This ensures that the parent process can receive the status information of the child process when its die.

Zombie Process is a very special in all of linux process, it has been abandoned almost all memory spaces, without any executable codes, also cannot be call, just keep a little places in the process talbe, records the process exit status so that the parent process can read it.

If his parent process did not call wait or waitpid() to wait for the child process die, it will keep in a zombie state.

If the parent process is end, the zombie child process becomes “orphan process“. A zombie process is not the same as an orphan process. An orphan process is a process that is still executing, but whose parent has died. They do not become zombie processes; instead, they are adoped by init process( process ID is 1), which will waits on its children.However, if a parent process isn’t programmed properly and never calls wait() or waitpid(), its zombie children will remain in memory until they’re removed.How to check the zombie process?

you can use the command PS, can see a marked Z process is a zombie process.

How to generate a zombie process?

According to the above description, it is easy to write a program to generate a zombie process, the following code:

#include <stdio.h>
 #include <sys/types.h>
int main()
 {
pid_t pid = fork(); // call fork() to fork a child process
if (pid > 0) //one call, return two value, child process return "0", parent process return child's process ID
 {
 printf("This is parent process!!!\n");
 sleep(60);
 printf("after sleeping, and exit!\n");
 }
 else if (pid == 0 )
 {
printf("This is the child process, and exit!\n");
 exit(0); //the child process exits, and it becomes a zombie process...
 }
return 0;
 }

 

The parent process did not call wait system call functions, thus become a zombie processes after the child process exit. We use the
following command to compile and run above codes, and then view the system process state:

root@devops:/# gcc zombieTest.c -o zombieTest
root@devops:/# ./zombieTest
This is the child process, and exit!
This is parent process!!!
after sleeping, and exit!

zombie1
It can be seen from the above, there was a zombie process. But if the parent process wake up after 60s, we view the system process information again, found the zombie process gone.I think you have known that, the zomibe process adopted to init process, and it will call wait system call to remove all orphan process.

How to get rid of zombie processes?

you can’t kill the zombie process with SIGKILL signal as you kill a normall process, As the zombie process can’t recive any signal. so having a good habit is very important.

Then when programming, how to get rid amount of zombie processes? According to the above description, the child process will send  SIGCHLD signals to the parent process when its dies. by default, this signal is ignored by system, so the best way is that we can call wait() in the  signal processing function, which could avoid the zombie stick around in the system. the example codes are as shown up:

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

sig_atomic_t child_exit_status;

void clean_up_child_process(int signal_num)
{
/* reomove child process */
int status;
wait (&status);

/* save exit status in a global variable */
child_exit_status = status;
}

int main()
{
/* handle SIGCHLD by calling clean_up_child_process */
struct sigaction sigchild_action;
memset(&sigchild_action, 0, sizeof(sigchild_action));
sigchild_action.sa_handler = &clean_up_child_process;
sigaction(SIGCHLD, &sigchild_action, NULL);

/* fork a child process */
pid_t c_pid;
c_pid = fork();
if (c_pid > 0)
{
printf("This is parent process!!!\n");
sleep(60);
}
else if(c_pid == 0)
{
printf("This is the child process, and exit!\n");
exit(0);
}
else
{
printf("fork failed!\n");
}

return 0;
}

 

Leave a Comment

You must be logged in to post a comment.