Click “Read the original text” to view Liangxu’s original video.
Link:https://juejin.im/post/5f20fbeae51d45348675fa78
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:

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

In a Mac system, it looks like this:

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…

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:

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:

Now open another terminal to see the process result:

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
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!!