SIGCLD信号及配合wait的使用

来源:互联网 发布:php 公众号开发源码 编辑:程序博客网 时间:2024/05/16 04:40

SIGCHLD的语义为:子进程状态改变后产生此信号,父进程需要调用一个wait函数以确定发生了什么。
对于SIGCLD的早期处理方式如下:

  • 1、如果进程特地设置该信号的配置为SIG_IGN,则调用进程的子进程将不产生僵死进程。
  • 2、如果将SIGCLD的配置设置为捕捉,则内核立即检查是否有子进程准备好被等待,如果是这样,则调用SIGCLD处理程序。

一般的,父进程在生成子进程之后会有两种情况,一种是父进程继续去做别的事情,另一种是父进程啥都不做,一直在wait子进程退出.
SIGCHLD信号就是为这第一种情况准备的,它让父进程去做别的事情,而只要父进程注册了处理该信号的函数,在子进程退出时就会调用该函数,在该函数中又可以调用wait得到终止的子进程的状态。处理信号的函数执行完后,再继续做父进程的事情.
也就是说,如果父进程在fork之后调用wait,就会阻塞,直到有一个子进程退出。
如果父进程在fork之前先signal(SIGCLD, sig_cld),即注册了SIGCLD的信号处理函数。然后做自己的事情。当子进程退出时,会给父进程发送一个SIGCLD信号。然后sig_cld函数就会执行。可以在sig_cld函数中调用wait获得子进程退出时的状态,并且此时wait不会阻塞。 当sig_cld函数执行完后,父进程又继续做自己的事情。
下面放一个apue上的例子:

#include    "apue.h"#include    <sys/wait.h>static void    sig_cld(int);intmain(){    pid_t    pid;    if (signal(SIGCLD, sig_cld) == SIG_ERR)        perror("signal error");    if ((pid = fork()) < 0) {        perror("fork error");    } else if (pid == 0) {        /* child */        sleep(2);        _exit(0);    }    pause();    /* parent */    exit(0);}static voidsig_cld(int signo)    /* interrupts pause() */{    pid_t    pid;    int        status;    printf("SIGCLD received\n");    if (signal(SIGCLD, sig_cld) == SIG_ERR)    /* reestablish handler */        perror("signal error");    if ((pid = wait(&status)) < 0)        /* fetch child status */        perror("wait error");    printf("pid = %d\n", pid);}
1 0
原创粉丝点击