您的位置:首页 > 其它

子进程的异步等待方式

2017-06-15 21:30 162 查看
通过之前所学的知识,我们可以了解到,通过wait函数或者waitpid函数可以清理僵尸进程,父进程可以通过两种方式等待子进程,一种是阻塞方式,另一种是非阻塞方式,而不管是那种方式,父进程都做不到完全不理会子进程而去完成自己的动作,即子进程不能达到异步等待的目的。

一、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自定义的忽略动作通常是没有区别的,但是这是一个特例。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: