In the fork ()/execve () process, assume that the parent process still exists at the end of the Child process, and the parent process fork () has not installed the sigchld signal processing function to call waitpid () when the sub-process ends and the signal is not explicitly ignored, the sub-process becomes a zombie and cannot end normally. In this case, even the root identity kill-9 cannot kill the zombie process. The remedy is to kill the parent process of the zombie process (the parent process of the zombie process must exist). The zombie process becomes an "orphan process" and passes the process init to process 1, init is always responsible for cleaning up zombie processes. A zombie process is a parent process that has exited and is not accepted by the dead process. It becomes a zombie process. The defunct process only has a record in the Process Table, and other resources are not occupied. Unless the number of processes in your system exceeds the limit, the zombie process will not have more disadvantages. Cause: 1. After the child process is terminated, it is called Zombie before the parent process calls wait. 2. Network reasons may sometimes cause zombie processes. Solution: 1. Set the sigcld signal to sig_ign, and the system will not produce zombie processes. 2. Use fork () twice, and exit the child process that follows immediately. The child process becomes an orphan process, so that the INIT process will be responsible for clearing the orphan process. How to generate botnets: When a process calls the exit command to end its own life, it is not actually destroyed, but it leaves a data structure called Zombie (the system calls exit, it is used to exit a process, but it is only limited to converting a normal process into a zombie process and cannot completely destroy it ). In the status of a Linux Process, a zombie process is a very special one. It has abandoned almost all the memory space, no executable code, and cannot be scheduled, only one location is retained in the process list, and information such as the exit status of the process is recorded for collection by other processes. In addition, zombie processes no longer occupy any memory space. It requires its parent process to collect dead parts for it. If its parent process does not have the sigchld signal processing function installed, it calls wait or waitpid () to wait until the child process ends, if the signal is not explicitly ignored, it will remain in zombie state. If the parent process ends, the INIT process will automatically take over the child process and send a zombie to it, it can still be cleared. However, if the parent process is a loop and does not end, the child process will remain zombie, which is why many zombie processes sometimes exist in the system. How to view botnets: Using the command ps, we can see that the process marked as Z is a zombie process. How to clear zombie processes: 1. Rewrite the parent process and send it to the dead after the child process dies. The specific method is to take over the sigchld signal. After a child process dies, it sends a sigchld signal to the parent process. After receiving the signal, the parent process executes the waitpid () function to collect the child process. This is based on the principle that even if the parent process does not call wait, the kernel will send sigchld messages to it, even though the default processing is ignored. If you want to respond to this message, you can set a processing function. 2. Kill the parent process. After the death of the parent process, the zombie process becomes an "orphan process". After it passes through to the INIT process on process 1, init will always be responsible for cleaning up the zombie process. All the zombie processes it generates will also disappear. ========================================================== === In Linux PS auwx Botnets discovered A All w/tty, including other users all windows and terminals, including processes of other users U user-oriented for users (user friendly) -W, W wide output wide format output X processes W/O controlling TTYs It will be marked after the zombie Process PS axf View the process tree and list the real processes in a tree PS axm The thread is listed. in Linux, the process and thread are unified. They are two lightweight processes. PS axu Displays the detailed status of a process. ========================================================== === Killall Kill-15 Kill-9 Generally, defunct processes cannot be killed. If kill-15 is used, more zombie processes will be generated after kill-9. Kill-kill PID Fuser-K PID You can consider killing the parent process, Kill-9 his parent process ========================================================== === A process that has been terminated but has not been well processed by its parent process (getting information about the final child process and releasing the resources it still occupies) is called a dead process (zombie process ). To avoid zombie: 1) In svr4, IF signal or sigset is called to set sigchld configuration to ignore, no zombie sub-process will be generated. In addition, you can set the sa_nocldwait flag to prevent sub-processes from freezing. This function can also be used in Linux. It is called at the beginning of a program. Signal (sigchld, sig_ign ); 2) Call fork twice. The Program 8-5 implements this. 3) Use waitpid to wait for the sub-process to return. ========================================================== === Zombie processes are zombie processes. First, it can be prevented by using functions such as wait and waitpid. The termination status of the process to release resources. The other is fork twice. ========================================================== === The defunct process only has a record in the Process Table, and other resources are not occupied. Unless the number of processes in your system exceeds the limit, the zombie process will not have more disadvantages. The only possible method is that the reboot system can eliminate the zombie process. ========================================================== === Any program has a zombie state, which occupies a little memory resources (that is, there is a record in the Process Table). It is just a representation and you don't have to be afraid. If there is a problem with the program, the simple and effective way to solve a large number of botnets is to restart. Kill is ineffective. Fork and zombie/defunct" The operating methods of some processes in UNIX. When a process dies, it does not completely disappear. The process is terminated, and it does not run any more, but there are some residual things waiting for the parent process to be withdrawn. These residual things include the returned values of sub-processes and other things. When the parent process fork () is a sub-process, it must use wait () or waitpid () to wait for the sub-process to exit. It is this wait () action that makes the child process residue disappear. Naturally, there is an exception in addition to the above rules: the parent process can ignore sigcld soft interruptions without wait (). You can do this (on a system that supports it, such as Linux ): Main () { Signal (sigcld, sig_ign);/* Now I don't have to wait ()! */ . . Fork (); Fork (); Fork ();/* rabbits, rabbits, rabbits! */ } Now, when a child process dies, the parent process does not have wait (). Usually PS shows it as "". It will always remain this way until the parent process wait (), or as follows. Here is another rule you must know: when the parent process dies before its wait () child process (assuming it does not ignore sigcld), the child process will put Init (pid1) process as its parent process. This is not a problem if the sub-process works well and can be controlled. However, if the sub-process is already defunct, we will have a little trouble. Look, the original parent process can no longer wait (), because it has vanished. In this way, how does init know the zombie processes such as wait. Answer: unpredictable. In some systems, init periodically destroys all of its defunct processes. In other systems, it simply rejects the parent processes of any defunct process, but destroys them immediately. If you use one of the above systems, you can write a simple loop and fill the process table with the defunct process that belongs to init. This probably won't make your system administrator very happy, right? Your task: Make sure that your parent process does not ignore sigcld or wait () It fork () all processes. However, you may not always do this (for example, you want to start a daemon or something else), but you must be careful with programming if you are a newbie to fork. In addition, do not be psychologically bound. Summary: The child process becomes defunct until the parent process wait (), unless the parent process ignores sigcld. Furthermore, the child process (active or defunct) of the parent process that does not have wait () disappears (assuming that the parent process does not ignore sigcld) becomes the child process of init, init processes them in a heavy way. The wait function is prototype: # Include/* define the pid_t type */ # Include Pid_t wait (int * Status) Once a process calls wait, it immediately blocks itself. Wait automatically analyzes whether a sub-process of the current process has exited. If it finds such a sub-process that has become a zombie, wait will collect information about this sub-process and destroy it completely and return it. If such a sub-process is not found, wait will be blocked until one appears. The status parameter is used to save some statuses when the collection process exits. It is a pointer to the int type. But if we don't care about how this sub-process died, we just want to destroy it (in fact, in most cases, we will think like this ), we can set this parameter to null, as shown below: PID = wait (null ); If the call succeeds, wait returns the ID of the collected sub-process. If the call process does not have a sub-process, the call fails. In this case, wait returns-1 and errno is set to echild. The function prototype of waitpid is: Introduction The prototype of waitpid system calling in the Linux function library is: # Include/* define the pid_t type */ # Include Pid_t waitpid (pid_t PID, int * status, int options) In essence, the functions of the system call waitpid and wait are exactly the same, but the waitpid has two more user-controlled parameters PID and options, this provides us with a more flexible way of programming. The following two parameters are described in detail: ● PID From the parameter name PID and type pid_t, we can see that what is needed here is a process ID. But when the PID gets different values, it has different meanings here. When the PID is greater than 0, only the child process whose process ID is equal to the PID is waiting. No matter how many other child processes have ended and exited, as long as the specified child process has not ended, waitpid will keep waiting. When pid =-1, wait for any sub-process to exit without any restrictions. At this time, waitpid and wait play the same role. When pid = 0, wait for any sub-process in the same process group. If the sub-process has been added to another process group, waitpid will not ignore it. PID <-1, wait for any sub-process in a specified process group, the ID of this process group is equal to the absolute value of PID. ● Options Options provides some additional options to control waitpid. Currently, only the wnohang and wuntraced options are supported in Linux. These two constants can be connected using the "|" operator, for example: Ret = waitpid (-1, null, wnohang | wuntraced ); If you do not want to use them, you can set options to 0, for example: Ret = waitpid (-1, null, 0 ); If the wnohang parameter is used to call waitpid, even if no sub-process exits, it will return immediately and will not wait forever like wait. However, the wuntraced parameter involves some tracking and debugging knowledge and is rarely used. There is not much to worry about here. Interested readers can check the relevant materials on their own. As you can see, smart readers may already see the clues-isn't wait a packaged waitpid? Check the <kernel source code directory>/include/unistd. h file 349-352 to find the following program segments: Static inline pid_t wait (int * wait_stat) { Return waitpid (-1, wait_stat, 0 ); } Returned values and errors The return value of waitpid is slightly more complex than that of wait. There are three cases: ● When the returned result is normal, waitpid returns the ID of the collected sub-process; ● If the wnohang option is set, and waitpid in the call finds that no child process has exited to collect data, 0 is returned; ● If an error occurs in the call,-1 is returned. errno is set to a value to indicate the error; When the sub-process indicated by the PID does not exist or this process exists but is not a sub-process that calls the process, waitpid will return an error, and errno is set to echild Others: Call wait & waitpid to process the terminated sub-process: Pid_t wait (int * Statloc ); Pid_t waitpid (pid_t PID, Int * statloc, Int options );Both functions return two values: the return value of the function and the ID of the terminated sub-process. The termination status of the sub-process is returned through the statloc pointer. The difference between wait and waitpid is obvious. Wait waits for the first child process to terminate, while waitpid can specify to wait for a specific child process. The difference may be more obvious in the following situations: When five clients connect to the server at the same time, that is to say, five sub-processes correspond to five customers respectively, at this time, the five customers almost simultaneously request termination. In this way, almost at the same time, five fin sends to the server. Similarly, five sigchld signals reach the server. However, Unix signals are usually not queued. Obviously, the signal processing function will only run once, the remaining four sub-processes reside in the kernel space as zombie processes. In this case, the correct solution is to use waitpid (-1, & stat, wnohang) to prevent zombie processes from being left behind. The PID is-1, indicating that the child process is waiting for the first termination, And the wnohang option notifies the kernel not to block when no terminated process item exists. Differences between wait and waitpid Waitpid provides three functions that cannot be implemented by Wait functions:
- Waitpid waits for a specific sub-process, and wait returns any terminated sub-process;
- Waitpid provides a non-blocking version of wait;
- Waitpid supports job control (with the wuntraced option ).
Macro used to check the termination status returned by the wait and waitpid functions: The sub-process statuses returned by these two functions are saved in the statloc pointer. You can use the following three macros to check the status:
- Wifexited (Status): true if it is terminated normally. This can be executed
- Wexitstatus (Status): takes the 8-bit lower value that the sub-process sends to the exit or _ exit parameter.
- Wifsignaled (Status): true if an exception is terminated. This can be executed
- Wtermsig (Status): gets the signal number that causes the sub-process to terminate.
- Wifstopped (Status): If the sub-process is currently suspended, it is true.
- Wstopsig (Status): gets the signal number that suspends the sub-process.
|