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 |
异步回收fork出的子进程(僵尸进程)
最新推荐文章于 2023-04-14 23:33:42 发布