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 }
相關文章
相關標籤/搜索