zombie process

僵尸进程:子进程退出后,父进程尚未回收子进程的资源,那么这个子进程就处于僵尸状态。
Q1:“资源”是些什么?
Q2:父进程如何回收子进程的资源?函数

内核为每一个终止子进程保存了必定量的信息,因此当终止进程的父进程调用wait或waitpid时,能够获得这些信息。
这些信息至少包括进程ID,该进程的终止状态,以及该进程使用的CPU时间总量.
内核能够释放终止进程所使用的全部存储区,关闭其全部打开的文件.spa

若是编写一个长期运行的程序,他调用fork产生了不少子进程,那么除非父进程等待来取得子进程的终止状态,不然这些子进程终止后就会变成僵尸进程。code

避免僵尸进程的方法
方法1:调用两次fork能够避免僵尸进程的产生。orm

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 
 5 int main(void)
 6 {
 7     pid_t pid;
 8 
 9     if ((pid = fork()) < 0)
10     {
11         printf("fork error\n");    
12         exit(-1);
13     }
14     else if (0==pid) /*first child*/
15     {
16         printf("1first child pid=%d\n", getpid());
17         if ((pid = fork())<0)
18         {
19             printf("fork error\n");    
20             exit(-1);
21         }
22         else if (pid > 0) /*parent from second fork == first child*/
23         {
24             printf("2first child pid=%d, first child exit\n", getpid());
25             exit(0);//first child exit
26         }
27 
28         printf("second child pid=%d\n", getpid());
29         /*I am the second child, my parent become init as soon as my real parent calls exit() in the statement above
30          * Here's where we'd continue executing, knowing that when we're done, init will reap out status*/
31         sleep(30);
32         printf("second child, parent pid = %d, second child exit\n", getppid());
33         exit(0);
34     }
35 
36     printf("pararent pid=%d\n", getpid());
37     if (waitpid(pid, NULL, 0) != pid) /*wait for first child*/
38     {
39         printf("waitpid error\n");    
40         exit(-1);
41     }
42     printf("parent exit");
43 
44 
45     /*I am the parent(the original process); I continue executing, knowing that I'm not the parent of the second child*/
46 
47     exit(0);
48 }

 


方法2:当SIGCHLD的处理方式是系统默认时,父进程调用了wait()以免僵尸进程的产生,此方法中,父进程阻塞。blog

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/wait.h>
 4 #include <errno.h>
 5 #include <signal.h>
 6 
 7 void print_exit(int status)
 8 {
 9     if (WIFEXITED(status))
10         printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
11     else if (WIFSIGNALED(status))
12         printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
13 #ifdef WCOREDUMP
14         WCOREDUMP(status) ? ("core file generated") : (""));
15 #else
16     "");
17 #endif
18     else if (WIFSTOPPED(status))
19         printf("child stopped, signal number=%d\n", WSTOPSIG(status));
20 }
21 
22 void sig_child(int signo)
23 {
24     int status;
25     int ret;
26     ret = wait(&status);
27     printf("pid:%d, res:%d, status=%d, %s\n", getpid(), ret, status, strerror(errno));
28     print_exit(status);
29 }
30 
31 void sig_usr(int signo)
32 {
33     if (signo == SIGUSR1)
34         printf("received SIGUSR1\n");
35     else if (signo == SIGUSR2)
36         printf("received SIGUSR2\n");
37     else
38         printf("received signal %d\n", signo);
39 }
40 
41 int main(int argc, char** argv)
42 {
43     pid_t pid;
44     int status;
45     int ret;
46 
47     if ((pid=fork()) < 0)
48     {
49         printf("fork error\n");
50         return -1;
51     }
52     else if (pid == 0)
53     {
54         printf("child exit\n");
55         return 0;
56     }
57     else
58     {
59         //printf("parent sleep(100)\n");
60         //sleep(100);
61         ret = wait(&status);
62         print_exit(status);
63         printf("parent exit\n");
64     }
65 
66 
67     exit(0);
68 }

 


方法3:当SIGCHLD的处理方式是捕获时,在其信号处理程序中调用wait()函数以免僵尸进程的产生,此方法中,父进程不阻塞。进程

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/wait.h>
 4 #include <errno.h>
 5 #include <signal.h>
 6 
 7 void print_exit(int status)
 8 {
 9     if (WIFEXITED(status))
10         printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
11     else if (WIFSIGNALED(status))
12         printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
13 #ifdef WCOREDUMP
14         WCOREDUMP(status) ? ("core file generated") : (""));
15 #else
16     "");
17 #endif
18     else if (WIFSTOPPED(status))
19         printf("child stopped, signal number=%d\n", WSTOPSIG(status));
20 }
21 
22 void sig_child(int signo)
23 {
24     int status;
25     int ret;
26     ret = wait(&status);
27     printf("pid:%d, res:%d, status=%d, %s\n", getpid(), ret, status, strerror(errno));
28     print_exit(status);
29 }
30 
31 void sig_usr(int signo)
32 {
33     if (signo == SIGUSR1)
34         printf("received SIGUSR1\n");
35     else if (signo == SIGUSR2)
36         printf("received SIGUSR2\n");
37     else
38         printf("received signal %d\n", signo);
39 }
40 
41 int main(int argc, char** argv)
42 {
43     pid_t pid;
44     struct sigaction act, oact;
45     int status;
46     int ret;
47 
48     act.sa_handler = sig_child;
49     sigemptyset(&act.sa_mask);
50     //act.sa_flags = 0|SA_NOCLDWAIT;
51     sigaction(SIGCHLD, &act, &oact);
52 
53     if ((pid=fork()) < 0)
54     {
55         printf("fork error\n");
56         return -1;
57     }
58     else if (pid == 0)
59     {
60         printf("child exit\n");
61         return 0;
62     }
63     else
64     {
65         printf("parent sleep(100)\n");
66         sleep(100);
67         printf("parent exit\n");
68     }
69 
70 
71     exit(0);
72 }

 

从打印中能够看出,信号处理程序由父进程调用
方法4:设置SIGCHLD为SA_NOCLDWAIT,当子进程终止时,不建立僵尸进程。父进程中不需调用wait。资源

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/wait.h>
 4 #include <errno.h>
 5 #include <signal.h>
 6 
 7 void print_exit(int status)
 8 {
 9     if (WIFEXITED(status))
10         printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
11     else if (WIFSIGNALED(status))
12         printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
13 #ifdef WCOREDUMP
14         WCOREDUMP(status) ? ("core file generated") : (""));
15 #else
16     "");
17 #endif
18     else if (WIFSTOPPED(status))
19         printf("child stopped, signal number=%d\n", WSTOPSIG(status));
20 }
21 
22 void sig_usr(int signo)
23 {
24     if (signo == SIGUSR1)
25         printf("received SIGUSR1\n");
26     else if (signo == SIGUSR2)
27         printf("received SIGUSR2\n");
28     else
29         printf("received signal %d\n", signo);
30 }
31 
32 int main(int argc, char** argv)
33 {
34     pid_t pid;
35     struct sigaction act, oact;
36     int status;
37     int ret;
38 
39     act.sa_handler = sig_usr;
40     sigemptyset(&act.sa_mask);
41     act.sa_flags = 0|SA_NOCLDWAIT;
42     sigaction(SIGCHLD, &act, &oact);
43 
44     if ((pid=fork()) < 0)
45     {
46         printf("fork error\n");
47         return -1;
48     }
49     else if (pid == 0)
50     {
51         printf("child exit\n");
52         return 0;
53     }
54     else
55     {
56         printf("parent sleep(100)\n");
57         sleep(100);
58         //ret = wait(&status);
59         //print_exit(status);
60         printf("parent exit\n");
61     }
62 
63 
64     exit(0);
65 }
相关文章
相关标签/搜索