SIGCHLD函数

SIGCHLD的产生条件

子进程终止时

子进程接收到SIGSTOP信号停止时

子进程处在停止态,接受到SIGCONT后唤醒时

借助SIGCHLD信号回收子进程

子进程结束运行,其父进程会收到SIGCHLD信号。该信号的默认处理动作是忽略。可以捕捉该信号,在捕捉函数中完成子进程状态的回收。

/***
sigchild.c
***/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

void sys_err(char *str)
{
    perror(str);
    exit(1);
}
void do_sig_child(int signo)
{
    int status;    pid_t pid;
    while ((pid = waitpid(0, &status, WNOHANG)) > 0) {
        if (WIFEXITED(status))
            printf("child %d exit %d\n", pid, WEXITSTATUS(status));
        else if (WIFSIGNALED(status))
            printf("child %d cancel signal %d\n", pid, WTERMSIG(status));
    }
}
int main(void)
{
    pid_t pid;    int i;
    for (i = 0; i < 10; i++) {
        if ((pid = fork()) == 0)
            break;
        else if (pid < 0)
            sys_err("fork");
    }
    if (pid == 0) {    
        int n = 1;
        while (n--) {
            printf("child ID %d\n", getpid());
            sleep(1);
        }
        return i+1;
    } else if (pid > 0) {
        struct sigaction act;
        act.sa_handler = do_sig_child;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        sigaction(SIGCHLD, &act, NULL);
        
        while (1) {
            printf("Parent ID %d\n", getpid());
            sleep(1);
        }
    }
    return 0;
}

 

/***
my_sigchild.c
***/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<signal.h>

void sys_err(char *str)
{
    perror(str);
    exit(1);
}

void do_sig_child(int signo)
{
    int status;
    pid_t pid;
    
    while( (pid = waitpid(0,&status,WNOHANG)) > 0)
    {
        if(WIFEXITED(status))
            printf("----------child %d exit %d\n",pid,WEXITSTATUS(status));
        else if(WIFSIGNALED(status))
        {
            printf("child %d cancel signal %d\n",pid,WTERMSIG(status));
        }
    }
}

int main()
{
    pid_t pid;
    int i;

    for(i = 0; i < 10; i++)
    {
        if((pid = fork()) == 0)
        {
            break;
        }
        else if(pid < 0)
        {    
            sys_err("fork");
        }    
    }

    if(0 == pid)
    {
        int n = 1;
        while(n--)
        {
            printf("child ID %d\n",getpid());
            sleep(1);
        }
        return i+1;
    }
    else if(pid > 0)
    {
        struct sigaction act;
        act.sa_handler = do_sig_child;
        sigemptyset(&act.sa_mask);

        while(1)
        {
            printf("Parent ID %d\n",getpid());
            sleep(1);    
        }

    }
    return 0;
}

 

分析该例子。结合 17)SIGCHLD 信号默认动作,掌握父使用捕捉函数回收子进程的方式。              【sigchild.c】

       如果每创建一个子进程后不使用sleep可以吗?可不可以将程序中,捕捉函数内部的while替换为if?为什么?

      if ((pid = waitpid(0, &status, WNOHANG)) > 0) { ... }

      思考:信号不支持排队,当正在执行SIGCHLD捕捉函数时,再过来一个或多个SIGCHLD信号怎么办?

posted @ 2019-08-11 20:26  王清河  阅读(767)  评论(0编辑  收藏  举报