I just wrote the official account at that time, and I recorded my study notes at that time. Now IT seems that there was a mistake recorded before, and I didn’t realize it at that time. Thank you liang Xu big guy in reprint my article when found and reminded.
If you make a mistake, you should correct it. Programmers should not be afraid of making mistakes
I do not know you look at their own years ago to do things, sometimes there is a feeling, this is what I do??
Okay, I kind of hate who I was
What is the relationship between parent and child processes?
process
Let’s start with what a process is:
Take a look at what Baidu has to say:
In Windows, it looks like this:
On the Mac, it looks like this:
In Linux, it looks like this:
[root@iz2ze76ybn73dvwmdij06zz ~]# ps -ef
UID PID PPID C STIME TTY TIME CMD
Root 1 0 0 May 20? 00:00:33 /usr/lib/systemd/systemd --system --deserialize 21Root 20 0 5 20? 00:00:00 [kthreadd]Root 3 20 5 20? 00:00:06 [ksoftirqd/0]Root 5 20 5 20? 00:00:00 [kworker/0:0H]Root 7 20 5月20? 00:00:02 [migration/0]Root 8 20 5 20? 00:00:00 [rcu_bh]Root 9 20 5 20? 00:30:40 [rcu_sched]Root 10 20 5 20? 00:00:17 [watchdog/0]Root 11 20 5 20? 00:00:16 [watchdog/1]Root 12 20 May 20? 00:00:02 [migration/1]Root 13 20 May 20? 00:00:03 [ksoftirqd/1]Root 15 20 May 20? 00:00:00 [kworker/1:0H]Root 17 20 May 20? 00:00:00 [kdevtmpfs]Root 18 20 May 20? 00:00:00 [netns]Root 19 20 May 20? 00:00:01 [khungtaskd]Root 20 20 May 20? 00:00:00 [writeback]Root 21 20 May 20? 00:00:00 [kintegrityd]Root 22 20 May 20? 00:00:00 [bioset]Root 23 20 May 20? 00:00:00 [kblockd]Copy the code
OK, each of the above lines is a description of a process. Let’s see what each parameter means:
mark | describe |
---|---|
UID | The user ID |
PID | The process ID |
PPID | The parent process ID |
C | Percentage of processes in the CPU |
STIME | Start time of the process |
TTY | Terminal location |
TIME | Actual CPU usage |
CMD | Commands and Parameters |
We now know what each parameter means, and since we’re talking about processes, first of all, process ids are unique and non-negative, but process ids can be reused, because processes also terminate.
You can see that no process has a PID of 0. Why is this? Black question mark?
0 is generally a system process that is part of the kernel and does not execute any on-disk programs.
fork
A process can create a new process by calling fork, which is called a child process.
Note that the return value of fork differs between parent and child processes.
- Child process: 0 is returned because the parent process of the child process can be uniquely identified. The id of the parent process can be obtained using getppID.
- Parent process: Returns the ID of the newly created child process, because a parent process can have more than one child process, and there is no such function to get all the ids of the thread’s children.
Let’s verify the above statement. Get the script ready.
#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 pid = %d, p1 = %d\n", getpid(), p1); } else { printf("Pid = %d, ppID = %d, p1 = %d\n", getpid(), getppid(), p1); } return 0; } Copy the code
Run to see results:
[root@iz2ze76ybn73dvwmdij06zz ~]# ./fork2
10213
Parent pid = 10212, p1 = 102130
Subprocess PID = 10213, PPID = 10212, p1 = 0Copy the code
In the example above we can see that the parent process returns the ID of the child process, and the child process returns 0.
An orphan
Orphans, we all know that…
Yes, that’s right, orphan processes are the same, processes without a parent. Of course, the parent process must be created first. When the parent process exits, its children (one or more) become orphan processes.
Let’s continue with a little test and let the parent process exit now. Get the script ready.
[root@iz2ze76ybn73dvwmdij06zz ~]# cat guer.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
int main(a){ 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 one step ~\n"); exit(0); } return 0; } Copy the code
Execute and see the result:
After the parent process exits, the child process is adopted by a process whose process ID is 1. The process whose id is 1 is init. Whenever an orphan process appears, init will adopt it and become its parent to take care of its future life.
harm
Orphan processes are harmless because they are taken over by the init process.
zombies
In contrast to the orphan process, this time the child process exits first, and the parent process does not recycle the child’s resources, so the child process becomes a zombie process.
Get the code ready:
[root@iz2ze76ybn73dvwmdij06zz ~]# cat zombie.c
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
int main(a) { pid_t pid; pid = fork(); if (pid < 0) { perror("fork error:"); exit(1); } else if (pid == 0) { printf("I'm the child process, I'm going to step out.\n"); printf("Child process ID: %d\n" ,getpid()); exit(0); } else { printf("I am the parent process, I sleep for 2 seconds \n"); printf("Parent process ID: %d\n" ,getpid()); sleep(2); while(2); // Do an endless loop without exiting } return 0; } Copy the code
Run to see the result:
Let’s open another terminal to see the result of the process:
As you can see, the child process does not exit completely, releasing resources, but becomes a zombie process.
harm
It can’t take up any resources. However, the number of processes in the system is usually limited. If a large number of zombie processes occupy the process number, new processes cannot be created. This harm is similar to occupying a pit.
To deal with
1. Kill the parent process
After the parent process is killed, the remaining child processes are orphaned, and the orphaned processes are adopted by the init process, which takes care of the resource release and so on.
2. The parent process calls wait or waitPID
Wait for the child to finish, which causes the parent to hang. When the wait () or waitPID () system call is executed, the child process immediately returns its data in the process table to the parent process, at which point the entry point is immediately deleted. In this case the Defunct process does not occur.
3. The fork twice
First fork: The parent forks a child
Second fork: The child process forks a grandchild process and exits
So the sun process is taken over by init, and when the sun process ends, init will recycle.
But the child process has to do its own recycling.
4. The signal function
SIGCHLD: install the SIGCHLD handler using signal. After the child process finishes, the parent process receives the signal and can call wait in the handler.
If the parent process does not care when the child process ends, the kernel can use the following two functions to tell the kernel that it is not interested in the child process’s end. In this case, the kernel will reclaim and no longer signal your parent process when the child process ends.
- Signal (SIGCLD, SIG_IGN)
- Signal (SIGCHLD, SIG_IGN)
conclusion
Originally thought a simple problem, did not expect this length is not short, so I feel programmers really can not say what knowledge point is simple, easy to understand ah, once you want to go deep is also need a certain amount of time to spend and energy ~
Reference:
-
Advanced Programming in UNIX Environments (Chinese Version 3)
-
http://suo.im/6tOqJz
-
http://suo.im/67gdou
Thanks for reading this article
This article is formatted using MDNICE