Hanover
Link: Defunct process zombie process
When testing a Demo of a directfb+gstreamer-based video network system, a large number of the statements that were invoked by the system, such as system ("./play") in the menu code, were executed several times, in this case, in the Ps-ef list There are a lot of defunct processes that are harmful to the running of the program. Supposedly the system's source code should already contain wait, but also can not exclude the development Board in this version of the system may not wait, in short, the Development Board after calling system after adding wait, the defunct process no longer exists.
The following talk about the defunct process, Chinese translation called the zombie process. The following is a book on networking and Apue.
First, what is a zombie process
In a UNIX system, a process is over, but his parent process does not wait (call Wait/waitpid) him, then he will become a zombie process. When you observe the execution state of a process with the PS command, you see that the status bar for these processes is defunct. The zombie process is a long-dead process, but still occupies a position (slot) in the Process table (processs table).
However, if the process's parent process has ended first, the process will not become a zombie process. Because at the end of each process, the system scans all the processes running in the current system to see if any process is a child of the process that just ended, and if so, the Init process takes over and becomes his parent process, guaranteeing that each process will have a parent process. While the init process automatically wait for its child processes, all processes that are taken over by Init do not become zombie processes.
Ii. How the process works under Unix
Each UNIX process has an entry point (entry) in the process table, and all the information that the core process uses to execute the process is stored at the entry point. When you look at the process information in the system with the PS command, you see the relevant data in the process table. When a new process is established with the fork () system call, the core process assigns the new process an entry point in the process table and stores the relevant information in the process table corresponding to that entry point. One of these messages is the identifier of the parent process.
The end of the child process and the run of the parent process are an asynchronous process in which the parent process can never predict when the child process will end. So will it be because the parent process is too busy to wait for the child process, or does it not know when the child process ends and loses the state information at the end of the child process?
No. Because UNIX provides a mechanism to ensure that the parent process can get the status information when it wants to know the end of the child process. This mechanism is: when the child process has finished its life cycle, it will execute the exit () system call, the kernel frees all the resources of the process, including open files, memory, etc. However, it still retains certain information (including the process ID, exit code exit codes, exit status of the Terminationstatus the process, run time the amount of the CPU taken B Y the process, etc.), this data will remain until the system passes it to its parent process until the parent process passes wait/waitpid to fetch.
In other words, when a process dies, it does not completely disappear. The process terminates, it no longer runs, but there is still some residual data waiting for the parent process to retract. When the parent process fork () a child process, it must wait for the child process to exit with wait () (or Waitpid ()). It is this wait () action to make the remaining data of the child process disappear.
Third, the harm of the zombie process
If the parent process does not call Wait/waitpid, then the reserved piece of information will not be released, its process number will always be occupied, but the system's process table capacity is limited, the number of processes can be used is also limited, if a large number of zombie processes are generated, The system cannot produce a new process because no process number is available.
Therefore, the defunct process not only consumes the system's memory resources, affects the performance of the system, but also causes the system to fail if the number is too large. Also, because the scheduler cannot select the defunct process, the defunct process cannot be deleted with the KILL command, only the only way to restart the system.
Iv. Generation of zombie processes
If the parent process does not have wait () when the child process dies, it is usually shown as "<defunct>" with PS, which results in a zombie process. It will always remain this way until the parent process wait ().
This shows that the defunct process occurs after the child process terminates, but before the parent process has read the data. With this we can use the following program to build a defunct process: C code
- #include <stdio.h>
- #include <sys/types.h>
- Main ()
- {
- if (!fork ())
- {
- printf ("Child pid=%d\n", Getpid ());
- Exit (0);
- }
- Sleep (20);
- printf ("Parent pid=%d \ n", Getpid ());
- Exit (0);
- }
When the above program is executed in the background, the 17th line forces the program to sleep for 20 seconds, giving the user time to enter the PS-E instruction, observing the status of the process, and we see that the defunct process is occurring in the process table. When the parent process is terminated and then observed with the PS-E command, we will see that the defunct process disappears as well. This is because after the parent process terminates, the INIT process takes over these orphan processes (orphan process) left by the parent process, and after the orphan process executes, its entry points in the process table are deleted. If a program is defective, it can cause the parent process of a process to be asleep or in a dead loop, the parent process does not have a wait child process, and it does not terminate for Init to take over, and after the execution of that child process it becomes the defunct process, which defunct The process may remain in the system until the system restarts.
Looking at an example of a zombie-producing process.
The procedure to be executed by the child process Test_prog
C code
- TEST.c
- #include <stdio.h>
- int main ()
- {
- int i = 0;
- For (i = 0; i <; i++)
- {
- printf ("Child Time%d\n", i+1);
- Sleep (1);
- }
- return 0;
- }
The code for the parent process Father Father.c
C code
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- int main ()
- {
- int pid = fork ();
- if (pid = = 0)
- {
- System ("./test_prog");
- _exit (0);
- }Else
- {
- int i = 0;
- /*
- int status = 0;
- while (!waitpid (PID, &status, Wnohang))
- {
- printf ("Father waiting%d\n", ++i);
- Sleep (1);
- }*/
- While (1)
- {
- printf ("Father waiting over%d\n", ++i);
- Sleep (1);
- }
- return 0;
- }
- }
Executes./father, a zombie process occurs when a child process exits, because the parent process does not pay attention to its exit.
C code
- 20786 pts/0 00:00:00 Father
- 20787 pts/0 00:00:00 Father <defunct>
Summary: The child process becomes defunct until the parent process wait (), unless the parent process ignores SIGCLD. Further, the parent process does not have a wait () to perish (still assuming that the parent process does not ignore SIGCLD) the child processes (active or defunct) become the child processes of Init, and Init begins to process them.
V. How to avoid the zombie process
1. The parent process waits for the child process to end through functions such as wait and waitpid, which causes the parent process to hang.
In the previous example, if we made a slight modification to execute the wait () or waitpid () system call before the 8th line of sleep () system call, the child process would immediately return the data in the process table to the parent process after it was terminated, and the entry point would be immediately deleted. In this case, the defunct process is not generated.
2. If the parent process is busy, you can use the signal function to install handler for SIGCHLD. After the child process finishes, the parent process receives the signal and can call the wait recycle in handler.
3. If the parent process does not care when the child process ends, the kernel can be notified with signal (SIGCLD, sig_ign) or signal (SIGCHLD, sig_ign) and is not interested in the end of the sub-process. After the child process is finished, the kernel recycles and no longer sends a signal to the parent process
4. Fork two times, the parent process fork a child process, and then continue to work, the child process fork a grandchild process, then exit, then the Sun process is init takeover, after the end of the sun process, init will be recycled. But the recycling of the sub-process to do it yourself. The following is an example of a Stevens that takes two folk to avoid a zombie process:
C code
- #include "apue.h"
- #include <sys/wait.h>
- Int
- Main (void)
- ... {
- pid_t pid;
- if (PID = fork ()) < 0) ... {
- Err_sys ("fork Error");
- } Else if (pid = = 0) ... { /**//* First child */
- if ((PID = fork ()) < 0)
- Err_sys ("fork Error");
- Else if (pid > 0)
- Exit (0); /**//* Parent from second fork = = First child */
- /**//*
- * We ' re the second child; Our parent becomes init as soon
- * As our real parent calls exit () in the statement above.
- * Here's where we ' d continue executing, knowing that's when
- * we ' re done, Init would reap our status.
- */
- Sleep (2);
- printf ("second child, parent PID =%d", getppid ());
- Exit (0);
- }
- if (waitpid (PID, NULL, 0)! = PID) /**//* Wait for first child */
- Err_sys ("Waitpid error");
- /**//*
- * We ' re the parent (the original process); We continue executing,
- * Knowing that we ' re not the parent of the second child.
- */
- Exit (0);
- }
Reprint--DEFUNCT Zombie Process