如果我只是使用wait()一次等待一个孩子完成,我是否需要对SIGCHLD处理程序做任何事情?

Cyber​​Skull

我有一个程序正在分叉给一个孩子去做一些工作,但是此时我一次只生一个孩子。我正在wait()等待孩子完成工作,是否还需要做任何事情SIGCHLD(例如禁用处理程序)?

在我的情况我得到的值,EINTRerrno这使我觉得我需要屏蔽SIGCHLD

概括地说,这是程序:

  • 读取参数
  • 为(要做的工作清单)
  • fork()
  • 如果是孩子,execlp()参加工作计划
  • 如果是父母,wait()要让孩子完成
  • 孩子完成后,父母会循环到下一个工作项目
乔纳森·勒夫勒(Jonathan Leffler)

理论

POSIX谈到SIG_IGN(严格在XSI扩展说明下):

如果将SIGCHLD信号的操作设置为SIG_IGN,则调用进程的子进程终止时不应转换为僵尸进程。如果调用进程随后等待其子进程,并且该进程没有未等待的子进程转换为僵尸进程,则它将阻塞直到其所有子进程终止,并且wait(),waitid()和waitpid()应失败,并将errno设置为[ECHILD]。

并在描述中<signal.h>说,对默认的信号配置SIGCHLDSIG_IGN“忽略”(代码“I”)。但是,它的SIG_DFL行为是“忽略”信号。永远不会产生信号。这与SIG_IGN行为不同

因此,您不必设置信号处理程序,但是您不应该获取有关该过程的信息-一旦没有子级,您应该得到一个错误。

示范代码

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static siginfo_t sig_info;
static volatile sig_atomic_t sig_num;
static void *sig_ctxt;

static void catcher(int signum, siginfo_t *info, void *vp)
{
    sig_num = signum;
    sig_info = *info;
    sig_ctxt = vp;
}

static void set_handler(int signum)
{
    struct sigaction sa;
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = catcher;
    sigemptyset(&sa.sa_mask);

    if (sigaction(signum, &sa, 0) != 0)
    {
        int errnum = errno;
        fprintf(stderr, "Failed to set signal handler (%d: %s)\n", errnum, strerror(errnum));
        exit(1);
    }
}

static void prt_interrupt(FILE *fp)
{
    if (sig_num != 0)
    {
        fprintf(fp, "Signal %d from PID %d\n", sig_info.si_signo, (int)sig_info.si_pid);
        sig_num = 0;
    }
}

static void five_kids(void)
{
    for (int i = 0; i < 5; i++)
    {
        pid_t pid = fork();
        if (pid < 0)
            break;
        else if (pid == 0)
        {
            printf("PID %d - exiting with status %d\n", (int)getpid(), i);
            exit(i);
        }
        else
        {
            int status = 0;
            pid_t corpse = wait(&status);
            printf("Child: %d; Corpse: %d; Status = 0x%.4X\n", pid, corpse, (status & 0xFFFF));
            prt_interrupt(stdout);
            fflush(0);
        }
    }
}

int main(void)
{
    printf("SIGCHLD set to SIG_IGN\n");
    signal(SIGCHLD, SIG_IGN);
    five_kids();
    printf("SIGCHLD set to catcher()\n");
    set_handler(SIGCHLD);
    five_kids();
    return(0);
}

fflush(0);调用可确保刷新标准输出(尤其是标准输出),如果将示例程序的输出通过管道传输到另一个程序,则这很重要。

示例输出

示例代码的输出与理论相符-但需要一些解释。

SIGCHLD set to SIG_IGN
PID 4186 - exiting with status 0
SIGCHLD set to SIG_IGN
Child: 4186; Corpse: -1; Status = 0x0000
PID 4187 - exiting with status 1
Child: 4187; Corpse: -1; Status = 0x0000
PID 4188 - exiting with status 2
Child: 4188; Corpse: -1; Status = 0x0000
PID 4189 - exiting with status 3
Child: 4189; Corpse: -1; Status = 0x0000
PID 4190 - exiting with status 4
Child: 4190; Corpse: -1; Status = 0x0000
SIGCHLD set to catcher()
PID 4191 - exiting with status 0
SIGCHLD set to catcher()
Child: 4191; Corpse: -1; Status = 0x0000
Signal 20 from PID 4191
Child: 4192; Corpse: 4191; Status = 0x0000
PID 4192 - exiting with status 1
Child: 4193; Corpse: 4192; Status = 0x0100
Signal 20 from PID 4192
PID 4193 - exiting with status 2
Child: 4194; Corpse: 4193; Status = 0x0200
Signal 20 from PID 4193
PID 4194 - exiting with status 3
Child: 4195; Corpse: 4194; Status = 0x0300
Signal 20 from PID 4194
PID 4195 - exiting with status 4

输出的第一部分与理论完全一致。调用代码不会获得有关已死亡子代的任何信息,只是没有等待等待的已死亡子代(左)。

输出的第二部分也与理论相符,但是看起来子代并没有在父代之前执行,因此父代的第一部分wait()没有等待死亡的子代,它返回-1。随后的呼叫得到了各种各样的孩子,但是一个逃生未等待(但是尸体将被系统清理)。如果使用的代码waitpid()如:pid_t corpse = waitpid(pid, &status, 0);,它将依次等待每个孩子。

根据上面有关“忽略”的修改后的注释,某些注释可能需要修订。待定-目前时间已过。

3 GHz Intel Core 2 Duo,GCC 4.6.0、64位编译器上的Mac OS X 10.8.4:

gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition sigchld.c -o sigchld 

这是一些现有的代码很快适应了测试的行为SIGINTpause()它可能包含一些多余的材料。您不必wait()在信号处理程序中致电或其亲戚之一;不过,如果您愿意,也可以这样做。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如果我升级内核,是否需要对grub做任何事情?

来自分类Dev

更新git版本...我需要对使用较旧git版本的存储库做任何事情吗

来自分类Dev

我试图做一个移动的对象,但是代码没有做任何事情。我想知道问题是什么?

来自分类Dev

我的一个子观点对任何事情都没有反应

来自分类Dev

Python 3 - 为什么我的简单程序不对输入做任何事情?

来自分类Dev

如果我在等待时不想做任何事情,使用实体框架异步方法有什么意义吗?

来自分类Dev

我有一个共同例程,一旦选定就可以播放。但是,如果我再次选择它,则不会发生任何事情。但是第一次确实有效

来自分类Dev

如何创建一个 redux-observable 史诗,在做任何事情之前等待 2 个动作

来自分类Dev

MySQL错误“即使我没有做错任何事情,DEFAULT子句中只能有一个带有CURRENT_TIMESTAMP的TIMESTAMP列”

来自分类Dev

不Thread.yield()做任何事情,如果我们有足够的处理器来服务所有主题?

来自分类Dev

-XStrict是否在GHC中做任何事情?

来自分类Dev

安装Ubuntu 12.04.3后,我收到一条消息“ Welcome To Grub!”。但我不能打字或做任何事情

来自分类Dev

安装Ubuntu 12.04.3后,我收到一条消息“ Welcome To Grub!”。但我不能打字或做任何事情

来自分类Dev

Math.round在我的网页上没有做任何事情

来自分类Dev

ActionScript 3 / MXML:我的代码没有做任何事情

来自分类Dev

为什么我的 ASP.NET 项目没有做任何事情?

来自分类Dev

我需要做任何事情来在我的非弧项目中通过Cocoapods使用RestKit 2.0吗?

来自分类Dev

如果我在 componentWillUnmount 中添加任何内容,则不会发生任何事情

来自分类Dev

为什么我们不需要为POST定义res.on('data'...,即使我们不对数据做任何事情?

来自分类Dev

我们可以对任何事情使用死锁吗?

来自分类Dev

C/C++ 套接字:如果我在它之前做任何事情,IPv6 TCP 连接就会失败

来自分类Dev

如果立即用Popen调用,然后从Python等待或休眠,为什么我的Perl脚本不做任何事情?

来自分类Dev

任何事件处理程序仅触发一次抽奖

来自分类Dev

为什么“如果”在此布尔方法中没有做任何事情?

来自分类Dev

“ make”命令没有做任何事情

来自分类Dev

“ make”命令没有做任何事情

来自分类Dev

cron工作没有做任何事情

来自分类Dev

如何停止做任何事情

来自分类Dev

Angular loadChildren 没有做任何事情

Related 相关文章

  1. 1

    如果我升级内核,是否需要对grub做任何事情?

  2. 2

    更新git版本...我需要对使用较旧git版本的存储库做任何事情吗

  3. 3

    我试图做一个移动的对象,但是代码没有做任何事情。我想知道问题是什么?

  4. 4

    我的一个子观点对任何事情都没有反应

  5. 5

    Python 3 - 为什么我的简单程序不对输入做任何事情?

  6. 6

    如果我在等待时不想做任何事情,使用实体框架异步方法有什么意义吗?

  7. 7

    我有一个共同例程,一旦选定就可以播放。但是,如果我再次选择它,则不会发生任何事情。但是第一次确实有效

  8. 8

    如何创建一个 redux-observable 史诗,在做任何事情之前等待 2 个动作

  9. 9

    MySQL错误“即使我没有做错任何事情,DEFAULT子句中只能有一个带有CURRENT_TIMESTAMP的TIMESTAMP列”

  10. 10

    不Thread.yield()做任何事情,如果我们有足够的处理器来服务所有主题?

  11. 11

    -XStrict是否在GHC中做任何事情?

  12. 12

    安装Ubuntu 12.04.3后,我收到一条消息“ Welcome To Grub!”。但我不能打字或做任何事情

  13. 13

    安装Ubuntu 12.04.3后,我收到一条消息“ Welcome To Grub!”。但我不能打字或做任何事情

  14. 14

    Math.round在我的网页上没有做任何事情

  15. 15

    ActionScript 3 / MXML:我的代码没有做任何事情

  16. 16

    为什么我的 ASP.NET 项目没有做任何事情?

  17. 17

    我需要做任何事情来在我的非弧项目中通过Cocoapods使用RestKit 2.0吗?

  18. 18

    如果我在 componentWillUnmount 中添加任何内容,则不会发生任何事情

  19. 19

    为什么我们不需要为POST定义res.on('data'...,即使我们不对数据做任何事情?

  20. 20

    我们可以对任何事情使用死锁吗?

  21. 21

    C/C++ 套接字:如果我在它之前做任何事情,IPv6 TCP 连接就会失败

  22. 22

    如果立即用Popen调用,然后从Python等待或休眠,为什么我的Perl脚本不做任何事情?

  23. 23

    任何事件处理程序仅触发一次抽奖

  24. 24

    为什么“如果”在此布尔方法中没有做任何事情?

  25. 25

    “ make”命令没有做任何事情

  26. 26

    “ make”命令没有做任何事情

  27. 27

    cron工作没有做任何事情

  28. 28

    如何停止做任何事情

  29. 29

    Angular loadChildren 没有做任何事情

热门标签

归档