Chinaunix首页 | 论坛 | 博客
  • 博客访问: 993173
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-12-08 12:10:34

10.7 SIGCLD semantics

SIGCLD是在system v的系列版本中使用的一个信号。SIGCHLDBSD系列版本中使用的信号,他们的意义有所不同,其中SIGCLD应该被禁用。其原因如下:

() system SIGCLD

SVR4是从system v发展出来的,它使用SIGCLD的方法(如下都以signalsigset函数作为signal安装函数)

1.被推荐的使用SIGCLD的方法

设置SIGCLDSIG_IGN,这样生成的孩子process在退出后不会生成zombia

2.不被推荐的使用方法

就是默认的对SIGCLD的处理方法,即SIG_DFL,子进程结束后不处理,如果父亲wait的话,会等所有的孩子进程结束后才返回-1errno=ECHLD。这不是推荐的。

 

可见在System v系列里,对SIGCLD的使用推荐使用SIG_IGN

 

3system vSIGCLD的一个被诟病的地方

就是当用signal安装SIGCLDhandler的时候,他会立马检查当前是否有孩子进程可以被waited,如果有,就立马调用handler。这会造成stack overflow,例如:我们用signal安装handler的时候,经常在signal handler里面首先将handler reinstall, 好,当有一个子进程结束了,发送了SIGCLD信号,该handler被调用,reinstall handler, 立马检查是否有可以waited的进程,有,立马调用handler, ….如此循环,不久死掉了么.

如下就是例子代码:

Figure 10.6. System V SIGCLD handler that doesn't work

#include      "apue.h"

#include     

 

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) {      /* child */

        sleep(2);

        _exit(0);

    }

    pause();    /* parent */

    exit(0);

}

 

static void

sig_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);

}

 

可见system v系列不能给SIGCLD安装handler,那么就只能采用推荐的方法SIG_IGN了。使其子进程压根不产生zombia.

 

(二)SIGCHLD

linux里,用signal安装SIGCHLD,且将handler置为SIG_IGN,也会达到是子进程退出后不产生zombia的好处。而默认的我们不处理该信号,就会产生zombiaBSD系列就是这样。

如下是摘自linux suse man page的一段话:

POSIX.1-1990 disallowed setting the action for SIGCHLD to SIG_IGN.  POSIX.1-2001 allows this  possibility, so that ignoring SIGCHLD can be used to prevent the creation of zombies (see wait(2)).  Nevertheless, the historical BSD and System V behaviors for ignoring SIGCHLD differ, so that  the  only  completely  portable  method  of ensuring that terminated children do not become zombies is to catch the SIGCHLD signal and perform a wait(2) or similar.

鉴于不同平台的对SIGCHLD的设置成SIG_IGN的意义的不同,唯一的更portable的避免zombia的方法是在SIGCHLDhandler里面调用wait

(三)使不产生zombia孩子的另一个方法

使用sigaction并设置SA_NOCLDWAIT标记

 

(四)在包括linux在内的一些平台,SIGCLD被宏定为SIGCHLD,放心使用

 

阅读(887) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~