父进程循环创建三个子进程, 并用sigchld完成对子进程的回收

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

//父进程循环创建三个子进程, 并用sigchld完成对子进程的回收
/*
1. fork 循环3次 if() 
2. 在父进程中注册信号处理函数,在子进程中睡眠,然后不同时间段退出
3. 设置未决信号集 , 阻塞信号集 , 将sigchld添加到阻塞信号集合中, 在完成信号注册后,解除对sigchld信号的阻塞. 这一步的目的是 : 为了防止父进程还没有完成对sigchld信号的注册, 子进程就结束了, 没有利用到sigchld回收子进程, 子进程就变成了僵尸进程
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask , SIGCHLD);
sigprocmask(SIG_BLOCK , &mask , NULL);

//注册
sigprocmask(SIG_UNBLOCK , &mask , NULL);
4. 注册信号处理函数的过程: 利用sigaction(SIGCHLD , ) 
struct sigaction act;
act.sa_handler = chld;
sigemptyset(&act.sa_mask); //清空信号集中的信号
act.sa_flags = 0;
sigaction(SIGINT , &act , NULL);

*/

void chld(int signo)
{
        pid_t wpid;
        while(1)
{
        wpid = waitpid(-1 , NULL , WNOHANG);
        if(wpid == 0 && wpid < 0)       //子进程还活着 没子进程活着了
        {
                break;
        }else if(wpid>0)        //子进程退出 返回子进程pid
        {
                printf("exit . child sig = [%d]\n" , wpid);
        }
}
}


int main()
{
        int i;
        sigset_t mask;
        sigemptyset(&mask);
        sigaddset(&mask ,SIGCHLD);
        sigprocmask(SIG_BLOCK , &mask , NULL);

        for(i=0; i<3; i++)
        {
                int pid = fork();
                if(pid < 0)
                {
                        perror("fork error");                   
                }
                else if(pid > 0)
                {
                        printf("father pid=[%d]\n", getpid());
                }
                else
                {
                        printf("son pid = [%d]\n",getpid());
                        break;                  //1. err1 这里应该break ,防止子进程创建子进程
                }
        }
        if(i==0)
        {
                printf("i==[%d], son pid = [%d]\n",i, getpid());
                sleep(1);       
        }
        if(i==1)
        {
                printf("i==[%d], son pid = [%d]\n",i, getpid());
                sleep(2);       
        }
        if(i==2)
        {
                printf("i==[%d], son pid = [%d]\n",i, getpid());
                sleep(1);       
        }
        else if(i==3)
        {       
                        struct sigaction act;
                        act.sa_handler = chld;
                        sigemptyset(&act.sa_mask);
                        act.sa_flags = 0;
                        //这里加延时 是为了模拟: 父进程还没来得及注册信号处理函数 , 子进程就全部退出了的情形!
                        sigaction(SIGCHLD , &act , NULL);

                        sigprocmask(SIG_UNBLOCK , &mask ,NULL);
                        while(1) 
                        {
                                sleep(1);       //sleep(1) 是为了防止空转速度过快
                        }
        }       
        return 0;
}

holo@holo:~/fwq$ ./sigchld
father pid=[33860]
son pid = [33861]
i==[0], son pid = [33861]
father pid=[33860]
son pid = [33862]
i==[1], son pid = [33862]
father pid=[33860]
son pid = [33863]
i==[2], son pid = [33863]


exit . child sig = [33861]
exit . child sig = [33863]


exit . child sig = [33862]

^C
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值