子进程的异步等待方式

通过之前所学的知识,我们可以了解到,通过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自定义的忽略动作通常是没有区别的,但是这是一个特例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值