在某些情况下忽略SIGCHLD而在其他情况下忽略SIGCHLD

时间:2009-03-10 18:24:39

标签: c unix system

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

在某些情况下,我想处理SIGCHLD并说出“Process#Finished”之类的内容。但在其他情况下,我想忽略这个信号。

我该怎么做?

4 个答案:

答案 0 :(得分:4)

为流程全局设置信号处理。如果你想在某些孩子终止而不是其他孩子的情况下捕获像SIGCHLD这样的异步信号,你就不能事先决定忽略它。

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

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

答案 1 :(得分:3)

您希望捕获信号SIGCHLD然后调用函数。您想使用signal()执行此操作(man signal)。在下面的示例中,在捕获信号SIGCHLD之后调用child_died()(此时子进程已停止)。如果有需要从子项传递给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 :(得分:2)

您可以在阻塞或非阻塞模式下使用waitpid功能来等待来自给定孩子的信号,然后进行一些处理。事实上,你使用某种类型的wait,正如格雷厄姆在答案中所述......

答案 3 :(得分:0)

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