3

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

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

我怎样才能做到这一点?

4

4 回答 4

4

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

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

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

于 2009-03-10T18:38:52.387 回答
3

你想捕捉信号 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()在父进程上调用,你需要一种将数据从子进程传输到父进程的方法。

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

于 2009-03-11T01:55:20.387 回答
2

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

于 2009-03-10T18:47:31.257 回答
0

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

于 2009-03-10T18:45:28.920 回答