子进程的异步等待方式

原来只给大家介绍过僵尸进程,而没有介绍僵尸进程是怎么回收的,今天就给大家介绍一下如何回收僵尸进程。

用wait和waitpid函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)。采用第一种方式,父进程阻塞了就不能处理自己的工作了;采用第二种方式,父进程在处理自己的工作的同时还要记得时不时地轮询一下(也就是过一段时间过来看一下是否有子进程退出然后回收它)。

其实,子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。

下面我们用自定义的信号捕捉函数来捕捉SIGCHLD信号。先让父进程fork出一个子进程,让子进程sleep3秒之后在退出,这时候我们对SIGCHLD信号进程捕捉,打印出我们想要的语句,这样就可以验证子进程会对父进程发送SIGCHLD信号。

测试如下:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void handler(int sig)
{
    printf("sig is: %d\n", sig);
}


int main()
{
    signal(SIGCHLD, handler);
    pid_t id = fork();
    if(id == 0)
    {
        printf("child is: %d, father is: %d\n", getpid(), getppid());
        exit(0);
    }
    else
    {
        printf("father is: %d\n", getpid());
        sleep(3);
    }
    return 0;
}

在上面的代码中我们让子进程先退出,这是我们对SIGCHLD信号进行了捕捉,然后在我们的捕捉函数中打印了捕捉的信号为17,而在下面我们可以看出17号信号为SIGCHLD。

父进程等待子进程的异步版本 :

首先必须介绍waitpid这个函数:

pid_t waitpid(pid_t pid, int *status, int options);
参数1:pid

Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
Pid==0等待其组ID等于调用进程组ID的任一个子进程。
Pid<-1等待其组ID等于pid绝对值的任一子进程。
参数2:status

WIFEXITED(status) : 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status) : 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

参数3:options

WNOHANG:非阻塞式等待指定的进程。

WUNTRACED:如果子进程进入暂停执行则马上返回,但结束状态不予以例会。

WCONTINUED:若实现支持作业控制,那么由pid指定的任一子进程在暂停后已经继续,但状态尚未报告,则返回状态。

下面我们直接测试子进程的已步等待方式

将waitpid的第一个参数设置为-1等待任何一个子进程,将参数3设置为WNOHANG非阻塞是等待进程。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void handler(int sig)
{
    pid_t id ;
    while((id = waitpid(-1,NULL,WNOHANG)) > 0)
    {
        printf("father:wait success:%d\n",id);
     }
    printf("child is quit! %d\n",getpid());
}


int main()
{
    signal(SIGCHLD, handler);
    pid_t id1 = fork();
    if(id1 == 0)
    {
        printf("child is: %d, father is: %d\n", getpid(), getppid());
        exit(0);
    }
    pid_t id2 = fork();
    if(id2 == 0)
    {
        printf("child is: %d, father is: %d\n", getpid(), getppid());
        sleep(1);
        exit(0);
    }
    printf("father is: %d\n", getpid());
    while(1)
    {
        printf("father is wait\n");
        sleep(1);
    }
    return 0;
}



在上面的代码中我们可以看出两个子进程分别是2907和2906,父进程为2905。当进程2069进程直接退出后给父进程发送了SIGCHLD信号,这时候父进程捕捉到了子进程发送的信号并打印了子进程的id 2906,然后打印自己的id 2905,等待了1秒后子进程2907退出给父进程发送了信号SIGCHLD,然后父进程接受并打印。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值