APUE编程:73---信号处理(SIGCLD、SIGHCLD信号处理)

一、SIGCLD、SIGHCLD信号

  • SIGCLD和SIGHCLD这两个信号很容易混淆:
    • SIGCLD是System V采用的信号名
    • SIGCHLD是BSD采用的信号名。POSIX.1也采用BSD的SIGCHLD信号
    • 只有Linux 3.2.0和Solaris 10定义了SIGCLD,SIGCLD等同于SIGCHLD
  • 务必了解你所使用的系统实现中SIGCHLD或SIGCLD信号的语义。也应了解在某些系统中#define SIGCHLD SIGCLD或#define SIGCLD SIGCHLD。更改这种信号的名字使你可以编译为另一个系统编写的程序,但是如果这一程序使用该信号的另一种语义,程序有可能不会正常工作。例如下面在Ubuntu下编译使用SIGCHLD信号的程序,出错

二、功能与特点

  • 子进程状态改变(终止或停止)后产生此信号(SIGCLD/SIGHCLD),传递给父进程
  • 如果父进程想要捕捉此信号,可以捕获该信号并进行处理

三、处理方式

  • SIGCLD信号的捕捉处理必须在子进程fork之前完成 

方式一:

  • 如果进程明确地将该信号配置为SIG_IGN,则调用进程的子进程将不产生僵死进程(注意:SIG_IGN与默认处理方式SIG_DFL不同)。子进程在终止时,将其状态丢弃
  • 如果调用进程随后调用一个wait()函数,那么它将阻塞直到所有的子进程都终止,然后该wait返回-1,并将errno设置为ECHILD

方式二:

  • 父进程为SIGCLD设置一个信号捕捉函数,在信号捕捉函数中调用wiat()或waittpid()获取子进程的终止状态与ID

四、一个重要案例

  • 下面的程序父进程为SIGCLD信号绑定信号处理函数,在信号处理函数中等待子进程结束
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

static void sig_cld(int);
int main()
{
    pid_t pid;
    if (signal(SIGCLD, sig_cld) == SIG_ERR)
        perror("signal error");

    if ((pid = fork()) < 0) {
        perror("fork error");
    } else if (pid == 0) { 
        sleep(2);
        _exit(0); //子进程终结
    }

    /* parent */
    //pause:使进程挂起,直到接收到一个信号并从信号处理函数中返回才结束挂起状态
    pause(); 

    exit(0);
}

static void sig_cld(int signo) 
{
    pid_t pid;
    int status;
    printf("SIGCLD received\n");

    if (signal(SIGCLD, sig_cld) == SIG_ERR) 
        perror("signal error");

    if ((pid = wait(&status)) < 0) //阻塞等待子进程,获得其进程号和终止状态
        perror("wait error");
    printf("pid = %d\n", pid);
}

演示结果: 

此程序在传统的System V平台上工作:

  • 会一直输出SIGCLD received,最后进程用完其栈空间并异常终止
  • 原因:信号处理程序第一次调用signal函数并且执行sig_cld处理函数,进入之后,内核检查是否有需要等待的子进程(因为我们正在处理一个SIGCLD信号,所以确实有这种子进程),所以它产生另一个对信号处理程序的调用,于是在sig_cld函数内继续调用sig_cld函数。整个过程再次重复
  • 解决办法:应当在调用wait取到子进程的终止状态后再调用signal。这样仅当其他子进程终止,内核才会再次产生此种信号

其他系统:

  • 不会产生上面这种问题,例如下面在Ubuntu中运行

  • 为什么举这个例子:虽然大多数系统都不会产生这种问题,但是还是有一些系统会产生这种问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董哥的黑板报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值