【问题标题】:Unexpected output with fork() [duplicate]fork() 的意外输出 [重复]
【发布时间】:2015-05-19 20:18:44
【问题描述】:

我在某处读到,在 Unix 中,在 fork() 成功执行后,两个进程都将在 fork() 调用之后的下一条语句开始执行。 同时,当我在 C 中运行此代码时

#include <stdio.h>
int main()
{
   printf(" do ");
   if(fork()!=0) printf ("ma ");
   if(fork()==0) printf ("to \n");
   else printf("\n")

    return 0;
}

一个可能的输出是

 do ma
 do ma to
 do 
 do to

"printf("做");"是 fork() 调用之前,那么“do”怎么会在输出中重复多次?

【问题讨论】:

  • 你分叉了两次......它应该是pid = fork(); if (pid) { ... } else { ...} 来检测你是在孩子还是父母身上。并且由于您的 do 输出没有换行符,因此它位于输出缓冲区中,直到遇到换行符,即 AFTER 您的 fork。所以你有两个缓冲区,其中有do
  • 其他人找到了 dups - 有负载 - 标准输出缓冲的东西。
  • 谢谢你的回答。我知道我要分叉两次,这是故意的,这是我老师的练习,我应该预测输出,但我仍然不明白为什么在两次分叉之前都写了好几次() 调用。
  • 好的,我找到了其中一个:)
  • 我认为“do”存在是因为它们缓冲在父输出内存中,该内存被复制到所有子代。

标签: c unix process output fork


【解决方案1】:

如果您看到 fork 的定义,它表示子代和父代是完全相同的副本,并且都从下一条指令开始执行。
现在,由于 C 在打印换行符或显式刷新输出之前不会刷新输出,因此“do”保留在缓冲区中并被复制到子级。
使用:

printf(" do ");
fflush(stdout);

printf(" do \n"); //Notice the newline in the end

你会得到预期的输出

【讨论】:

  • 这与“中级”与“高级”无关。
  • 中级与高级对于这种解释来说是相当抽象的。仍然将其删除,因为它不是答案的一部分。
【解决方案2】:

我认为“do”在那里是因为它们缓冲在复制到所有子级的父级输出内存中。

如果在第一个“do”后面加上“\n”:

printf(" do\n");

在分叉之后你不会看到任何“做”。

【讨论】:

    【解决方案3】:
       if(fork()!=0) printf ("ma ");
    

    这一行创建了两个进程;其中一个是父级并运行 printf 语句,一个是子级并且不运行。

       if(fork()==0) printf ("to \n");
    

    两个进程都运行这条语句;结果是四个进程:

    1. 父母-父母;这会运行第一个 printf 并打印“do ma”
    2. 父子;这会同时运行并打印“do ma to \n”
    3. 子父;这既不运行,也打印“做”
    4. 儿童-儿童;这将运行第二个并打印“do to \n”

    您遇到的问题是您认为 fork 返回“跳过”到下一条语句;相反,当 fork 返回时,您现在有两个具有不同返回值的进程。通常,在程序结束或打印换行符之前不会刷新 printf。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-20
      • 2013-02-02
      • 2012-04-07
      • 1970-01-01
      • 2013-07-07
      • 2021-10-20
      • 2015-08-31
      • 1970-01-01
      相关资源
      最近更新 更多