Understanding Zombie and Orphan Processes in Linux

Understanding Zombie and Orphan Processes in LinuxUnderstanding Zombie and Orphan Processes in Linux

Click “Read the original text” to view Liangxu’s original video.

Link:https://juejin.im/post/5f20fbeae51d45348675fa78

At that time, I had just started writing on WeChat, and these were my study notes. Now looking back, I realize there was a mistake I recorded back then that I didn’t notice.

If you make a mistake, you have to correct it. Programmers can’t be afraid of making mistakes~

Does anyone else feel like when looking at things they did years ago, sometimes they think, is this really me???

Well, I have a bit of disdain for my past self~

Let’s get straight to the point, what is the relationship between parent and child processes?

Process

First, let’s talk about what a process is:

Let’s see how Baidu describes it:

Understanding Zombie and Orphan Processes in Linux

Just looking at the description isn’t very vivid, in a Windows system, it looks like this:

Understanding Zombie and Orphan Processes in Linux

In a Mac system, it looks like this:

Understanding Zombie and Orphan Processes in Linux

In Linux, it looks like this: (screenshot is a bit long, just part of it)

[root@iz2ze76ybn73dvwmdij06zz ~]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 5月20 ?       00:00:33 /usr/lib/systemd/systemd --system --deserialize 21
root         2     0  0 5月20 ?       00:00:00 [kthreadd]
root         3     2  0 5月20 ?       00:00:06 [ksoftirqd/0]
root         5     2  0 5月20 ?       00:00:00 [kworker/0:0H]
root         7     2  0 5月20 ?       00:00:02 [migration/0]
root         8     2  0 5月20 ?       00:00:00 [rcu_bh]
root         9     2  0 5月20 ?       00:30:40 [rcu_sched]
root        10     2  0 5月20 ?       00:00:17 [watchdog/0]
root        11     2  0 5月20 ?       00:00:16 [watchdog/1]
root        12     2  0 5月20 ?       00:00:02 [migration/1]
root        13     2  0 5月20 ?       00:00:03 [ksoftirqd/1]
root        15     2  0 5月20 ?       00:00:00 [kworker/1:0H]
root        17     2  0 5月20 ?       00:00:00 [kdevtmpfs]
root        18     2  0 5月20 ?       00:00:00 [netns]
root        19     2  0 5月20 ?       00:00:01 [khungtaskd]
root        20     2  0 5月20 ?       00:00:00 [writeback]
root        21     2  0 5月20 ?       00:00:00 [kintegrityd]
root        22     2  0 5月20 ?       00:00:00 [bioset]
root        23     2  0 5月20 ?       00:00:00 [kblockd]

OK, each line above describes a process. Let’s take a closer look at what each parameter means:

Identifier Description
UID User ID
PID Process ID
PPID Parent Process ID
C CPU percentage used by the process
STIME Time the process started
TTY Terminal location
TIME Actual CPU time used
CMD Command and parameters

Now we know what each parameter means, since we’re talking about processes, the process ID is unique and non-negative, but the process ID can be reused, after all, processes do terminate.

We can see that there is no process with PID 0, why is that? A puzzled face?

0 is generally a system process, part of the kernel, and does not execute any programs on disk.

Fork

A process can create a new process by calling the fork function, and the created process is called a child process.

It’s important to note the return value of the fork function differs for parent and child processes.

  • Child Process: The return value is 0, the reason for returning 0 is that the parent process of the child process can be uniquely determined, and can be obtained through the getppid method.
  • Parent Process: The return value is the ID of the newly created child process, because a parent process can have multiple child processes, and there is no such function to get all the IDs of the child threads of that thread.

Next, let’s verify what we just said. Prepare the script.

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    pid_t p1 = fork();
    printf("%d\n",p1);
    if(p1 > 0)
    {
        printf("Parent process pid = %d, p1 = %d\n", getpid(), p1);
    }
    else
    {
        printf("Child process pid = %d , ppid = %d, p1 = %d\n", getpid(), getppid(), p1);
    }
    return 0;
}

Run to see the result:

[root@iz2ze76ybn73dvwmdij06zz ~]# ./fork2
10213
Parent process pid = 10212, p1 = 10213
0
Child process pid = 10213 , ppid = 10212, p1 = 0

From the small example above, we can see that the return value of the parent process is the ID of the child process, and the return value of the child process is 0.

Orphan Process

We all understand that an orphan is…

Understanding Zombie and Orphan Processes in Linux

Yes, that’s right, an orphan process is just like that, it is a process without a parent process. Of course, it must first create a parent process when created, and when the parent process exits, its child processes (one or more) become orphan processes.

Next, let’s do another small test, let the parent process exit first. Prepare the script.

[root@iz2ze76ybn73dvwmdij06zz ~]# cat guer.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

int main()
{
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork error;");
        exit(1);
    } else if (pid == 0) {
        sleep(5);
        printf ("Child process : [ pid] = %d , Parent process [ppid] = %d\n",getpid(),getppid());
        exit(0);
    } else if (pid > 0) {
        printf("I am the parent thread, I will exit first~\n");
        exit(0);
    }
  return 0;
}

Execute and see the result:

Understanding Zombie and Orphan Processes in Linux

At this point, many of you may have already understood that after the parent process exits, the child process is adopted by a process with the ID of 1. This result is quite good, at least someone is taking care of it, which warms my heart~ The process with ID 1 is the init process, and whenever an orphan process appears, the init process will adopt it and become its parent process, taking care of its life as an orphan process in the future.

Hazards

Since orphan processes are taken over by the init process, they are not hazardous.

Zombie Process

In contrast to orphan processes, this time the child process exits first, while the parent process does not handle the resource recovery of the child process, at this point, the child process becomes a zombie process.

First, prepare the code:

[root@iz2ze76ybn73dvwmdij06zz ~]# cat zombie.c
  #include <stdio.h>
  #include <unistd.h>
  #include <errno.h>
  #include <stdlib.h>

  int main()
  {
      pid_t pid;
      pid = fork();
     if (pid < 0)
     {
         perror("fork error:");
         exit(1);
     }
     else if (pid == 0)
     {
         printf("I am the child process, I will exit first.
");
         printf("Child process id : %d\n" ,getpid());
         exit(0);
     } else {
         printf("I am the parent process, I will sleep for 2 seconds\n");
         printf("Parent process id : %d\n" ,getpid());
         sleep(2);
         while(2); // A dead loop, one that does not exit
    }
   return 0;
 }

Run to see the result:

Understanding Zombie and Orphan Processes in Linux

Now open another terminal to see the process result:

Understanding Zombie and Orphan Processes in Linux

As you can see, the child process has not completely exited and released resources, but has become a zombie process.

Hazards

In terms of resources, it does not occupy much. However, the number of processes in the system is usually limited, and if there are a large number of zombie processes occupying process IDs, it can prevent new processes from being created, which is similar to occupying a pit without doing anything.

Handling

1. Kill the parent process

After killing the parent process, the remaining child processes become orphan processes, and after becoming orphan processes, they behave as we said above, with the init process adopting these processes and handling the resource release of these processes.

2. The parent process calls wait or waitpid

These functions wait for the child process to end, which will cause the parent process to hang. When executing wait() or waitpid() system calls, the child process will immediately return its data in the process table to the parent process after termination, and the system will immediately delete that entry. In this case, no defunct processes will be generated.

3. Fork twice

The first fork: the parent process forks a child process

The second fork: the child process forks a grandchild process and then exits

Then the grandchild process is taken over by init, and when the grandchild process ends, init will recycle it.

But the recycling of the child process still needs to be done by itself.

4. Signal function

The parent process handles: by using the signal function to install a handler for SIGCHLD, when the child process ends, the parent process will receive that signal and can call wait in the handler to recycle.

The kernel handles: If the parent process does not care when the child process ends, it can notify the kernel that it is not interested in the child process’s termination with the following two functions. At this point, after the child process ends, the kernel will recycle it and will not send a signal to the parent process.

  • signal(SIGCLD, SIG_IGN)
  • signal(SIGCHLD, SIG_IGN)

Conclusion

I originally thought this was a simple issue, but I didn’t expect this length to not be short, so I feel that programmers can’t just say a knowledge point is simple and easy to understand. Once you want to delve into it, it also requires a certain amount of time and energy~

References:

  • “Advanced Programming in the UNIX Environment (Chinese Third Edition)”

  • http://suo.im/6tOqJz

  • http://suo.im/67gdou

Liangxu’s personal WeChat

Add Liangxu’s personal WeChat to receive 3 sets of essential materials for programmers

→ Selected technical materials shared

→ High-level communication community

Understanding Zombie and Orphan Processes in Linux

All articles in this public account have been organized into a directory. Please reply “m” in the public account to get it!

Recommended reading:

This software only 1.5M can make your internet speed 3 times faster

Using Vim to read and write remote files in Linux

Comic: What is a “design pattern”?

5T technical resources released! Including but not limited to: C/C++, Linux, Python, Java, PHP, Artificial Intelligence, Microcontrollers, Raspberry Pi, etc. Reply “1024” in the public account to get it for free!!

Understanding Zombie and Orphan Processes in Linux

Leave a Comment

×