[Linux inter-process communication] 05. Zombie process

【Linux Interprocess Communication】

Project code acquisition:https://gitee.com/chenshao777/linux-processes.git
(Please order a free Star, your Star is my motivation for writing!)

05. Zombie process

Zombie process: means that after the process terminates, resources are not recovered, and the status is Z +
How to create a zombie process, it is very simple,
Create a child process through the fork function
The parent process executes while(1) infinite loop,
The child process does not loop, and exits directly after running a few statements.
For example:

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

/*
    Zombie process & amp; child process sends signal to parent process (via kill(getppid(), sig)) & amp; child process calls exit(), sends SIGCHLD signal to parent process
    Command: ./z + process
    Phenomenon: The parent process is running normally and receives a SIGUSR1 signal from the child process
         If the child process does not call the exit() function to end, it will become a zombie process Z +
         When the child process calls the exit() function to end, it sends a SIGCHLD signal to the parent process, and the parent process signal processing function calls the wait() function to reclaim the child process resources
*/
void handler(int arg)
{<!-- -->
    printf("signal processing handler, arg = %d\\
", arg); //arg is the signal ID
    if(arg == SIGINT)
        printf("You pressed ctrl + c \\
");
    if(arg == SIGUSR1)
        printf("The parent process received the signal from the child process\\
");
    if(arg == SIGCHLD){<!-- -->
        printf("When the child process terminates, it will send a SIGCHLD signal to the parent process, telling the parent process to recycle itself\\
");
        wait(NULL); //Recycle child process resources
    }
}

int main(int argc, char *argv[])
{<!-- -->
    signal(SIGINT, handler); //SIGINT (ctrl + c) signal processing

    pid_t pid;
    pid = fork();

    if(pid > 0){<!-- -->
        signal(SIGUSR1, handler); //Receive the signal of the child process
        // signal(SIGCHLD, handler); //Receive the signal of the end of the child process
        printf("parent process\\
");
        for(int i = 0;i < 10;i ++ ){<!-- -->
            printf("parent %d\\
",i);
            sleep(1);
        }
    }
    if(pid == 0){<!-- -->
        printf("The child process runs, then sleeps for 2 seconds\\
");
        sleep(2);
        printf("Send signal to parent process\\
");
        kill(getppid(), SIGUSR1);

        sleep(1);
        printf("The child process is fart by itself, the state of the child process changes, and the SIGCHLD signal is automatically sent to the parent process\\
");
    }
    return 0;
}

This code combines the signal signal processing function. The introduction of the signal function can be used for reference in the third section of my previous blog [Linux inter-process communication] 04. Signal communication between Linux processes

Run result:

hc@hc-vm:~/Linux_ARM/git/linux-processes/04. signal communication $ gcc 04.z + process.c -o z + process
hc@hc-vm:~/Linux_ARM/git/linux-processes/04. signal communication $ ./z + process
parent process
parent 0
The child process runs, then sleeps for 2 seconds
father 1
Send a signal to the parent process
father 2
Signal processing handler, arg = 10
The parent process receives a signal from the child process
father 3
The child process is fart by itself, and the state of the child process changes, and automatically sends a SIGCHLD signal to the parent process
father 4
father 5
father 6
father 7
father 8
father 9

After the child process executes the statement, it ends directly. Let’s run the ps -axj command to check the status of the process

 PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  4070 30199 30199 4070 pts/1 30199 S + 1000 0:00 ./z + process
 30199 30200 30199 4070 pts/1 30199 Z + 1000 0:00 [z + process] <defunct>
  2282 30207 30207 2282 pts/0 30207 R + 1000 0:00 ps -axj

The first line is the parent process information, the second line is the child process information
The parent process is in the S + sleep state (maybe just executing the sleep function)
child process is Z + zombie process state

Handle zombie processes:

First of all, we need to know two knowledge points:

1. Function of wait() function: Once the parent process calls wait, it will block itself immediately, and wait will automatically analyze whether a child process of the current process has exited, if it finds such a child process that has exited child process, wait will collect the information of this child process, and return after completely destroying it;

If no such child process is found, wait will block here until one appears.
2. As long as the running state of the child process changes, it will automatically send a SIGCHLD signal to the parent process, so the parent process sets a processing function for the SIGCHLD signal, and uses it in the processing function The wait() function performs resource recovery of the child process.

signal(SIGCHLD, handler); //Receive the signal of the end of the child process

Although the above code says that the exit of the child process is to send the SIGCHLD signal to the parent process, the signal is ignored by default.

———————————————
So how to deal with zombie processes:

1. Set the SIGCHLD signal processing function in the main process
2. Execute wait(NULL) in the signal processing function, and perform resource recovery on the exited child process, then the zombie process does not exist.

Specific operation:
Put the above code in
// signal(SIGCHLD, handler); //Receive the signal of the end of the child process
Cancel the comment, run it again, and check the running result and process status:

hc@hc-vm:~/Linux_ARM/git/linux-processes/04. signal communication $ gcc 04.z + process.c -o z + process
hc@hc-vm:~/Linux_ARM/git/linux-processes/04. signal communication $ ./z + process
parent process
parent 0
The child process runs, then sleeps for 2 seconds
father 1
Send a signal to the parent process
Signal processing handler, arg = 10
The parent process receives a signal from the child process
father 2
father 3
The child process is fart by itself, and the state of the child process changes, and automatically sends a SIGCHLD signal to the parent process
Signal processing handler, arg = 17
When the child process terminates, it will send a SIGCHLD signal to the parent process, telling the parent process to recycle itself
father 4
father 5
father 6
father 7
father 8
father 9

There is an extra sentence in the running result “When the child process terminates, it will send a SIGCHLD signal to the parent process to tell the parent process to recycle itself”
It means that the main process received the SIGCHLD signal after the child process exited, and executed the following code in the handler function

if(arg == SIGCHLD){<!-- -->
    printf("When the child process terminates, it will send a SIGCHLD signal to the parent process, telling the parent process to recycle itself\\
");
    wait(NULL); //Recycle child process resources
}

Since wait(NULL); is running, there is no zombie process in the process state, only the main process in S + state

 PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
  4070 30533 30533 4070 pts/1 30533 S + 1000 0:00 ./z + process
  2282 30535 30535 2282 pts/0 30535 R + 1000 0:00 ps -axj

Extend your knowledge:

If the parent process ends early and the child process is still running, who will reclaim resources for the child process when the child process exits?
Answer: If the child process is still running, but the parent process exits early, the init process with PID 1 will automatically take over and become the parent process of the child process, and recycle resources after the child process terminates(Linux kernel real cow)

syntaxbug.com © 2021 All Rights Reserved.