等待C中的进程

时间:2013-11-19 03:21:09

标签: c unix fork wait zombie-process

我一直在阅读关于wait()waitpid()的文档,我仍然对它们的工作方式感到有些困惑(我收集到wait(&status)等同于waitpid(-1, &status, 0); })。下面是我正在研究的一小段代码。请帮助我理解这些片段是否写得正确,如果没有,那么为什么不这样。

目标1: 收获所有僵尸儿童。

int reapedPid;
do {
    reapedPid = waitpid(-1,NULL,WNOHANG);
} while (reapedPid > 0);

我在这里尝试做的是遍历所有孩子,如果孩子已经完成,就让孩子收获,如果不是,就让它继续下去,当我的孩子用尽时reapedPid == -1然后循环退出。我在这里感到困惑的原因是我没有看到waitpid()应该知道哪些孩子已经被检查过,哪些没有被检查过。它做了这样的检查吗?或者这种方法不起作用?

目标2: 等待所有孩子完成。

int pid;
do {
    pid = wait(NULL);
} while (pid != -1);

这里我不关心孩子的结果状态 - 这应该只是等待每个子进程完成,无论是成功还是不成功,然后退出。我认为这段代码是正确的,但我不确定。

目标3: 分叉一个孩子并等待它完成。

int pid = fork();
if (pid < 0) {
    // handle error.
}
else if (pid == 0) {
    // execute child command
}
else {
    int status;
    int waitedForPid = waitpid(pid,&status,0);
    assert(waitedForPid == pid);
}

这里我只是试图分叉过程并让父母等待孩子完成。我不完全确定我是否应该通过0选项,但看起来WNOHANG,WUNTRACED和WCONTINUED与我的目标并不相关。

2 个答案:

答案 0 :(得分:2)

对于大多数这些,您应该能够轻松编写一些示例程序并验证您的理解。

目标1: 收获所有僵尸儿童。

  

我在这里感到困惑的原因是我不知道waitpid()应该知道哪些孩子已经被检查过,哪些没有被检查过。它做了这样的检查吗?

一旦孩子退出,只能wait一次。因此,您的循环只会获取尚未wait(僵尸)的子进程的退出状态。

对于目标2和3 ,再次,我会认为这是一个必需的练习,以编写示例以查看其工作原理。对于#2,我建议您的代码应该始终跟踪所有分叉的子代,以便它可以准确地知道wait上的人。你的#3代码看起来不错;不需要options。请务必使用WEXITSTATUS和朋友宏从status获取信息。

另见:

答案 1 :(得分:2)

  1. 跟踪进程是内核的工作。跟踪死亡过程是微不足道的。内核可以判断哪些子进程已经死亡但尚未等待,并且每次调用都将返回其中一个死亡的子进程,直到没有任何进程报告为止。 (由于WNOHANG选项,可能仍有孩子需要等待,但剩下的孩子都没有死。但

  2. 这第二个循环也很好,几乎等同于第一个循环。不同之处在于它会在返回-1之前等待所有孩子死亡。

  3. 这第三个片段很好;断言将是真实的,除非在特殊情况下(例如程序中的另一个线程也等待孩子并收集尸体)。但是,如果你在某个地方启动另一个进程并让它在后台运行,你可能会收集僵尸,而通过修改其他循环,你可以收集僵尸并仍然等待正确的孩子:

    int pid = fork();
    
    if (pid < 0)
    {
        // handle error.
    }
    else if (pid == 0)
    {
        // execute child command
    }
    else
    {
        int status;
        int corpse;
        while ((corpse = waitpid(-1, &status, 0)) > 0)
            if (corpse == pid)
                break;
    }