【问题标题】:Ignoring SIGCHLD in some cases but not others在某些情况下忽略 SIGCHLD,但在其他情况下不忽略
【发布时间】:2010-10-12 12:16:17
【问题描述】:

在我的程序中,我根据用户输入 fork() 多次。

在某些情况下,我想处理 SIGCHLD 并说出类似“进程 # 完成”之类的内容。但在其他情况下,我想忽略此信号。

我该怎么做?

【问题讨论】:

    标签: c unix system


    【解决方案1】:

    你想捕捉信号 SIGCHLD 然后调用一个函数。您想使用 signal() 来执行此操作 (man signal)。在下面的示例中,child_died() 在信号 SIGCHLD 被捕获后被调用(此时子进程已死)。如果有您需要从子级传递给父级的信息,child_died() 需要一个条件,您将需要使用管道 (man pipe)。下面是一个信号和管道的例子:

    #include <signal.h>
    #include <strings.h>
    #include <stdio.h>
    
    #define MAX_SIZE 256
    
    void child_died(int);
    
    int fd[2];
    
    int main()
    {
        int pid;
        extern int fd[];
        char *str;
    
        pipe(fd);
        signal(SIGCHLD, child_died);
    
        if ((pid = fork()) < 0) {
            // error
            printf("Error\n");
        } else if (pid == 0) {
            // child
            printf("In child process\n");
            close(fd[0]);
            str = strdup("Message from child process.\n");
            write(fd[1], str, strlen(str) + 1);
        } else {
            // parent
            wait();
            printf("Now in parent\n");
        }
    
        return 0;
    }
    
    void child_died(int s)
    {
        char *str;
        close(fd[1]);
        read(fd[0], str, MAX_SIZE);
        printf("%s", str);
    }
    

    保存为 sigchld.c 并编译为:gcc -Wall sigchld.c -o sigchld

    如果您想将一个 int(如子 pid)或其他一些数据类型从子进程传递给父进程,您要么必须将其转换为字符串并再次返回,要么找到另一种方法它。

    如果您想忽略 SIGCHLD,那么在我的示例中,您可以将该逻辑放入 child_died()。只需使用简单的if。我不知道您是如何决定何时忽略信号以及何时打印您想要的,这就是我在上面的代码中包含管道内容的原因。我想您会使用来自子进程的一些信息,并且由于在父进程上调用了 child_died(),因此您需要一种将数据从子进程传输到父进程的方法。

    我希望这会有所帮助。可能有更好或更简单的方法来实现这一点,我不知道。如果有,请评论。

    【讨论】:

      【解决方案2】:

      您可以在阻塞或非阻塞模式下使用waitpid 函数来等待来自给定子节点的信号,然后进行一些处理。实际上,您必须使用某种wait,正如格雷厄姆的回答中所述...

      【讨论】:

        【解决方案3】:

        如果您忽略 SIGCHLD,那么进程表将被僵尸填满。

        【讨论】:

        【解决方案4】:

        为进程全局设置信号处理。如果您想在某些子节点终止但其他子节点不终止时捕获像 SIGCHLD 这样的异步信号,您不能决定提前忽略它。

        您需要每次在父级中处理信号,然后决定是否要在处理程序中忽略它。

        至少,您的处理程序应该对子进程(siginfo_t 结构中的 si_pid)执行 wait() 以获取其返回码。此时,您可以检查进程 ID 并决定还要做什么。如果您不想打印,则无需打印任何内容。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-23
          • 2016-06-10
          • 1970-01-01
          相关资源
          最近更新 更多