平时如果不太注意创建子进程的处理,有可能会导致僵尸进程,以至于有一天系统无法创建进程,超过系统允许的最大进程数。如果不捕捉SIGCHLD信号,子进程退出时,系统默认释放进程的内核结构。如果捕捉了,但父进程没有调用wait或waitpid等函数获取子进程的退出状态,那么在父进程还没有退出时,子进程就会成为僵尸进程。另外一种情况,由于linux信号不等待,可能丢失了信号,父进程也没有获取子进程的退出状态。
linux防止僵尸进程的代码
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
| #include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
void sig_child(int signo)
{
pid_t pid;
//解决信号不排队的状况,假如两个子进程同时退出,信号SIGCHLD只有一个,通过while俩防止出现这种情况
while ((pid = waitpid(-1, NULL, 0)) > 0)
{
printf("Handler reaped child %d\n", (int)pid);
}
if (errno != ECHILD)
{
printf("waitpid error\n");
}
sleep(2);
return;
}
int main(int argc, char **argv)
{
int index, n;
char buf[1024];
pid_t pid;
//建立SIGCHLD信号处理函数,获取子进程的退出状态,防止出现僵尸进程
if(signal(SIGCHLD, sig_child) == SIG_ERR)
{
printf("signal error\n");
}
for (index = 0; index < 3; index++)
{
if((pid = fork()) == 0)
{
printf("Hello from child %d\n", (int)getpid());
sleep(1);
exit(0);
}
}
//处理慢系统调用被信号打断的情况
while ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0)
{
if (errno != EINTR)
{
printf("read error\n");
}
}
printf("Parent processing input\n");
while (1);
exit(0);
}
|