子进程的异步等待方式
2017-06-15 21:30
162 查看
通过之前所学的知识,我们可以了解到,通过wait函数或者waitpid函数可以清理僵尸进程,父进程可以通过两种方式等待子进程,一种是阻塞方式,另一种是非阻塞方式,而不管是那种方式,父进程都做不到完全不理会子进程而去完成自己的动作,即子进程不能达到异步等待的目的。
一、SIGCHLD信号
1、关于SIGCHLD信号
子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程就可以进行自己的动作而不必管理子进程,子进程只需要在退出时通知父进程,父进程在信号处理函数中调用wait函数来清理子进程即可。
2、举例说明
该程序的运行结果如下:
说明:父进程fork一个子进程,子进程调用exit(2)终止,父进程自定义SIGCHLD信号处理函数,在handler函数中获得子进程的退出状态并打印。
二、不产生僵尸进程的另一种方法
父进程调用sigaction函数将SIGCHLD信号的处理动作设置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。
举例说明:
该程序的运行结果如下:
说明:系统默认的忽略动作和用户用sigaction自定义的忽略动作通常是没有区别的,但是这是一个特例。
一、SIGCHLD信号
1、关于SIGCHLD信号
子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程就可以进行自己的动作而不必管理子进程,子进程只需要在退出时通知父进程,父进程在信号处理函数中调用wait函数来清理子进程即可。
2、举例说明
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> void handler(int sig) { do{ pid_t ret=waitpid(-1, NULL, 0); if(ret>0) { printf("wait success: %d\n",ret); break; } else { printf("wait filed!\n"); break; } } while(1); } int main() { signal(SIGCHLD,handler); pid_t id=fork(); if(id==0) { printf("i am child - pid : %d\n",getpid); sleep(2); exit(1); } else { while(1) { printf("do father thing\n"); sleep(1); } } return 0; }
该程序的运行结果如下:
说明:父进程fork一个子进程,子进程调用exit(2)终止,父进程自定义SIGCHLD信号处理函数,在handler函数中获得子进程的退出状态并打印。
二、不产生僵尸进程的另一种方法
父进程调用sigaction函数将SIGCHLD信号的处理动作设置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。
举例说明:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> int main() { struct sigaction act,oact; act.sa_handler=SIG_IGN; act.sa_flags=0; sigemptyset(&act.sa_mask); sigaction(SIGCHLD,&act,&oact); pid_t id=fork(); if(id==0) { printf("i am child - pid : %d\n",getpid()); sleep(3); exit(1); } else { while(1) { printf("do father thing\n"); sleep(1); } } return 0; }
该程序的运行结果如下:
说明:系统默认的忽略动作和用户用sigaction自定义的忽略动作通常是没有区别的,但是这是一个特例。