【问题标题】:How can waitpid() reap more than one child?waitpid()怎么会收割多个孩子呢?
【发布时间】:2022-11-25 05:16:56
【问题描述】:

在 CSAPP 书籍第 8 章的这个例子中:


\#include "csapp.h"

/* WARNING: This code is buggy! \*/

void handler1(int sig)
{
int olderrno = errno;

    if ((waitpid(-1, NULL, 0)) < 0)
        sio_error("waitpid error");
    Sio_puts("Handler reaped child\n");
    Sleep(1);
    errno = olderrno;

}

int main()
{
int i, n;
char buf[MAXBUF];

    if (signal(SIGCHLD, handler1) == SIG_ERR)
        unix_error("signal error");
    
    /* Parent creates children */
    for (i = 0; i < 3; i++) {
        if (Fork() == 0) {
            printf("Hello from child %d\n", (int)getpid());
            exit(0);
        }
    }
    
    /* Parent waits for terminal input and then processes it */
    if ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0)
        unix_error("read");
    
    printf("Parent processing input\n");
    while (1)
        ;
    
    exit(0);

}

它生成以下输出:

......
Hello from child 14073
Hello from child 14074
Hello from child 14075
Handler reaped child
Handler reaped child //more than one child reaped
......

用于waitpid() 的 if 块用于生成waitpid() 无法收割所有孩子的错误。虽然我知道 waitpid() 将被放入 while() 循环中以确保收割所有孩子,但我不明白的是 为什么只有一个waitpid()调用,却能够收获多个孩子(注意输出中有多个孩子被处理程序收获)?根据这个回答:Why does waitpid in a signal handler need to loop? waitpid()只能收割一个孩子。

谢谢!

更新:这无关紧要,但处理程序已按以下方式更正(也取自 CSAPP 书):

void handler2(int sig) 
{
    int olderrno = errno;

    while (waitpid(-1, NULL, 0) > 0) {
        Sio_puts("Handler reaped child\n");
    }
    if (errno != ECHILD)
        Sio_error("waitpid error");
    Sleep(1);
    errno = olderrno;
}

在我的 Linux 计算机上运行这段代码。

【问题讨论】:

    标签: c operating-system computer-science cpu-architecture signal-handling


    【解决方案1】:

    每次收到您分配给它的信号(在本例中为SIGCHLD)时,您指定的信号处理程序就会运行。虽然 waitpid 确实在每次信号接收时只执行一次,但处理程序仍会执行多次,因为每次子进程终止时都会调用它。

    孩子 n 终止(SIGCHLD),处理程序开始行动并使用 waitpid“收割”刚刚退出的孩子。

    子节点 n+1 终止,其行为与子节点 n 相同。这适用于每个孩子。

    不需要循环它,因为它只在需要时才被调用。

    【讨论】:

    • 在书中,他们确实使用了 while 循环来纠正这个问题:请参阅我的更新。
    猜你喜欢
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多