Linux避免僵尸进程两种方式

什么是僵尸进程


子进程退出时,父进程并未对其发出的SIGCHLD信号进行适当处理,导致子进程停留在僵死状态等待其父进程为其收尸,这个状态下的子进程就是僵死进程。

僵尸进程将会占据系统资源,由于系统的进程ID是有限的,所以大量的僵尸进程会导致用户创建进程失败。

避免僵尸进程两种方式


一、 父进程可以马上退出,使得子进程成为孤儿进程,由系统将子进程的ppid改为1(init进程),并由init进程来回收子进程的资源。

实现这一要求的技巧是fork两次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
pid_t pid;
if((pid = fork())<0){
printf("fork err\n");
exit(0);
}else if(pid == 0){
if((pid = fork())<0){
printf("fork err\n");
exit(0);
}else if(pid > 0){
//第一次fork的子进程退出,此时第二次fork的子进程还在活动(sleep),
//退出后第二次fork的子进程将成为孤儿进程
exit(0);
}
sleep(2);
printf("second child,parent pid = %d\n",getppid());
exit(0);
}
//父进程等待第一次fork的子进程退出,由于子进程调用了exit(0),所以可以很快回收子进程资源并退出
if(waitpid(pid,NULL,0)!= pid){
printf("waitpid error\n");
exit(0);
}
exit(0);
}

二、 父进程声明一个信号处理函数,得到子进程的退出信号,然后在信号处理函数调用wait函数彻底结束子进程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<signal.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
pid_t pid;
void handle_child(int sig)
{
//得到子进程的退出信号后调用wait函数释放子进程资源
if(waitpid(pid,NULL,0)!=pid){
printf("waitpid error\n");
exit(0);
}
printf("child exit\n");
exit(0);
}
int main()
{
(void) signal (SIGCHLD,handle_child);
if((pid = fork())<0){
printf("fork error\n");
exit(0);
}
if(pid == 0){
//子进程睡眠2秒后退出
sleep(2);
exit(0);
}
while(1)
{
sleep(1);
}
}