异步回收fork出的子进程(僵尸进程)

fork()之后,非阻塞(异步)等待子进程(回收僵尸)。
fork()之后,子进程和父进程分叉执行,僵尸进程的产生是因为父进程没有给子进程“收尸”造成的,又可以根据危害程度分为下述两类:
总体来说:当子进程结束之后,但父进程未结束之前,子进程将成为僵尸进程。
(1)当子进程结束之后,但父进程未结束之前,子进程将成为僵尸进程,父进程结束后僵尸被init进程回收。
(2)如果子进程结束了,但是父进程始终没有结束,那么这个僵尸将一直存在,而且随着exec,僵尸越来越多。
如下面的代码,在父进程执行的5s内,子进程将为僵尸:
查看源代码
打印帮助
01    /*
02     * main.cc
03     *
04     *  Created on: 2009-12-3
05     *      Author: liheyuan
06     *    Describe:
07     *
08     *   Last Date: 2009-12-3
09     *   CopyRight: 2009 @ ICT LiHeyuan
10     */
11    
12    #include <stdio.h>
13    #include <stdlib.h>
14    #include <signal.h>
15    #include <unistd.h>
16    
17    int main() {
18        //子进程的pid
19        int c_pid;
20        int pid;
21    
22        if ((pid = fork())) {
23            //父进程
24            c_pid = pid;
25            printf("The child process is %d\n", c_pid);
26            sleep(5);
27            exit(0);
28        } else {
29            //子进程
30            printf("I 'm a child.\n");
31            exit(0);
32        }
33    }

如上面的代码,在父进程的5s内,子进程一直是僵尸!
因此,需要对僵尸进程进行回收,传统的回收方法是,使用wait()函数,等待子进程,wait()是阻塞模式的,当子进程没有结束之前,wait一直等待,不往下面的语句执行。
查看源代码
打印帮助
01    /*
02     * main.cc
03     *
04     *  Created on: 2009-12-3
05     *      Author: liheyuan
06     *    Describe:
07     *
08     *   Last Date: 2009-12-3
09     *   CopyRight: 2009 @ ICT LiHeyuan
10     */
11    
12    #include <stdio.h>
13    #include <stdlib.h>
14    #include <signal.h>
15    #include <unistd.h>
16    #include <sys/wait.h>
17    
18    int main() {
19        //子进程的pid
20        int c_pid;
21        int pid;
22    
23        if ((pid = fork())) {
24            //父进程
25            c_pid = pid;
26            printf("The child process is %d\n", c_pid);
27            //阻塞等待子进程
28            int status;
29            if ((pid = wait(&status)) != -1 && pid == c_pid) {
30                //成功回收子进程
31                printf("The child exit with %d\n", WEXITSTATUS(status));
32                fflush(stdin);
33            } else {
34                printf("wait() fail.\n");
35            }
36            printf("Now , The child has been exit , and I will sleep.\n");
37            sleep(20);
38            exit(0);
39        } else {
40            //子进程
41            printf("I 'm a child.\n");
42            sleep(5);
43            exit(0);
44        }
45    }

转载自:4号程序员

如上面的代码,在子进程执行5秒后,即被回收,在夫进程的20秒内,子进程已经被结束,不再是僵尸。
但是这种利用wait()阻塞等待的方法也有一定的缺陷,那就是父进程必须等待子进程,无法做其他事情,如何非阻塞的等待子进程呢?
man wait,查看NOTES章节,可以找到:
子进程退出的时候,会发送SIGCHLD信号,默认的POSIX不响应,所以,我们只需要把处理SIGCHLD的函数自己实现就OK了,怎么作呢?
signal用于设置处理信号量的规则(或跳转到的函数)
查看源代码
打印帮助
01    signal(SIGCHLD,handler);
02    void handler(int num)
03    {
04        //我接受到了SIGCHLD的信号啦
05        int status;
06        int pid = waitpid(-1,&status,WNOHANG);
07        if(WIFEXITED(status))
08        {
09            printf("The child exit with code %d",WEXITSTATUS(status));
10        }
11    }



OK,全部代码如下,注意父进程不要再用wait阻塞啦!
查看源代码
打印帮助
01    /*
02     * main.cc
03     *
04     *  Created on: 2009-12-3
05     *      Author: liheyuan
06     *    Describe:
07     *
08     *   Last Date: 2009-12-3
09     *   CopyRight: 2009 @ ICT LiHeyuan
10     */
11    
12    #include <stdio.h>
13    #include <stdlib.h>
14    #include <signal.h>
15    #include <unistd.h>
16    #include <sys/wait.h>
17    
18    void handler(int num) {
19        //我接受到了SIGCHLD的信号啦
20        int status;
21        int pid = waitpid(-1, &status, WNOHANG);
22        if (WIFEXITED(status)) {
23            printf("The child %d exit with code %d\n", pid, WEXITSTATUS(status));
24        }
25    }
26    
27    int main() {
28        //子进程的pid
29        int c_pid;
30        int pid;
31    
32        signal(SIGCHLD, handler);
33    
34        if ((pid = fork())) {
35            //父进程
36            c_pid = pid;
37            printf("The child process is %d\n", c_pid);
38    
39            //父进程不用等待,做自己的事情吧~
40            for (int i = 0; i < 10; i++) {
41                printf("Do parent things.\n");
42                sleep(1);
43            }
44    
45            exit(0);
46        } else {
47            //子进程
48            printf("I 'm a child.\n");
49            sleep(2);
50            exit(0);
51        }
52    }

转载请注明出处:http://www.coder4.com/index.php/archives/151

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值