【问题标题】:fork() and waitpid possible outputsfork() 和 waitpid 可能的输出
【发布时间】:2013-12-02 18:18:09
【问题描述】:

我的教科书给出了以下主要例程:

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

它询问可能的输出是什么,我找到了 3 个:

abcc:操作系统选择首先执行的子进程,并打印“a”。然后,操作系统暂停子进程并恢复父进程,打印“b”。然后父必须等到子完成,子打印“c”,最后父打印“c”。

bacc:操作系统选择首先运行的父进程,并打印“b”。然后父母必须等待孩子完成并打印“ac”。然后父级打印“c”。

acbc:操作系统选择子节点先运行直到完成,打印“ac”。然后父进程运行完成,打印“bc”。

但是,教科书中还列出了一个答案,bcac。我不明白这是怎么可能的,因为如果首先打印 b,那么父母必须等待孩子继续,然后打印“ac”,然后父母会打印“c”,给出我已经列出的 bacc .有什么我遗漏的吗,或者说只有 3 个可能的输出是否正确?

【问题讨论】:

  • 就像 acbc 一样,父叉子完成,然后子叉子完成,bcac 是子叉子完成,然后父叉子完成。 bcac 是 false (b) > 外部条件 (c) > 退出 > true (a) > 外部条件 (c) > 退出的结果
  • 我认为fork(或printf)失败的情况不考虑?
  • 我认为你是对的,而教科书是错的。孩子的ac 总是在waitpid() 返回之前打印(exit(3) 隐式调用fflush(2))。由于父级在waitpid 之后打印c,因此ac 不能在末尾。
  • bcac 仅在您假设另一个孩子已经终止(显然不是这种情况,因为我们知道只有一个孩子被催生了!)或 write 调用由 @987654333 完成时才有可能@ 当 C 库在子退出时刷新其缓冲区时,在父进程中的 printf 完成 write 调用之后实现。这在理论上是可能的,但这是一种极其人为的假设诡辩。对于任何合理的想法,这是不可能的。
  • 假设printf() 的代码将自己与一个线程关联,即父线程。现在父进程将运行,打印b,然后等待子进程。孩子将ac 发送到printf()printf() 现在没有为孩子提供服务,因此孩子完成并且父母的c 被打印。 printf(),现在完成了父母的打印任务,转而为孩子服务并打印待处理的ac。所以,你得到bcac。请记住,printf() 前面有 1 个或多个队列,除非每个 printf() 都附有 fflush(),否则它们可能无法按打印顺序提供服务。 cout 包括 fflush()

标签: c fork waitpid


【解决方案1】:

不要总是相信教科书...

来自errata

p。 772,练习题 8.3 的解法。序列 bcac 不是 可能的。删除倒数第二句。最后一句应该 be “有三种可能的序列:acbc、abcc 和 bacc。”请 请参阅 Web Aside 页面上的 Web Aside ECF:GRAPHS 以获取 过程图。

【讨论】:

    猜你喜欢
    • 2012-08-29
    • 1970-01-01
    • 2012-11-09
    • 2016-03-19
    • 1970-01-01
    • 2012-11-24
    • 1970-01-01
    • 2019-05-17
    • 2012-03-10
    相关资源
    最近更新 更多