等待过程返回

时间:2014-08-13 01:14:30

标签: c process waitpid

考虑:

int main()
{
        if (fork() == 0){
            printf("a");
        }
        else{
            printf("b");
            waitpid(-1, NULL, 0);
        }
        printf("c");
        exit(0);
 }

(来自Computer Systems,Bryant - O'Hallaron)。

我们被要求提供所有可能的输出序列。

我回答:acbc,abcc,bacc。 但是,与解决方案(bcac)相比,我缺少一个输出。我认为这个输出是不可能的,因为父进程在打印c(waitpid)之前等待它的子进程返回。这不是真的吗?为什么?并且,在这种情况下,上面的代码和没有waitpid行的代码有什么区别?

2 个答案:

答案 0 :(得分:3)

我没有看到任何方式bcac是可能的。起初我期望一些基于stdio缓冲区以意外顺序刷新的技巧。但即便如此:

在输出c之后,孩子不会输出a。因此,c中的第一个bcac必须来自父级。

c完成之后,父母不会输出waitpid。但这种情况在孩子完成之后才会发生,包括在exit()期间发生的最终stdio同花。因此,第一个c总是来自孩子。

已经实现了矛盾证明......输出不能是bcac

嗯,你可以做一件事来弄乱订单。您可以在已经有一个即将退出的子进程的进程内执行该程序。如果预先存在的子项在新子项打印a之前退出,则主进程将检测 退出waitpid,并继续打印其内容并可能退出在孩子打印之前。

这在setuid程序中需要注意:不要假设因为您的程序只创建了一个子进程,它只有一个子进程。如果您处于高级防御代码学习环境中,这个答案是有道理的。在unix-newbie语境中,它看起来并不相关,而且只说bcac是不可能的,即使它在技术上并不正确,也可能更好。

答案 1 :(得分:2)

这很棘手,但可以中断对waitpid的调用(返回-1而错误号为EINTR)。在这种情况下,父级可以在子级输出任何内容之前输出c,并且bcac是可能的。

为了防止发生bcac,需要设置信号掩码,或者更好的是,检查waitpid返回值,如果中断则再次调用。