【问题标题】:Statement before fork() printing twice [duplicate]fork() 打印两次之前的语句[重复]
【发布时间】:2012-05-28 20:03:07
【问题描述】:

我正在尝试使用fork() 和重定向来检查在父级中完成的重定向是否也适用于子级。我写了以下简单的程序

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main ()
{
    freopen( "error.txt", "w+t", stdout ); // From now on, stdout = error.txt
    printf (" ERROR!  WHY DONT U UNDERSTAND?\n");
    if ( fork() == 0 ) 
    {   
        printf(" I AM CHILD\n");
        exit(0);
    }   
    else-
    {   
        printf (" EITHER I AM A PARENT OR SOMETHING GOT SCREWED\n");
    }   


    return 0;
}

我得到的输出(error.txt)是

ERROR!  WHY DONT U UNDERSTAND?
EITHER I AM A PARENT OR SOMETHING GOT SCREWED
ERROR!  WHY DONT U UNDERSTAND?
I AM CHILD

令人惊讶的是,ERROR! WHY DONT U UNDERSTAND?打印了两次,尽管它出现在 fork() 被调用之前很久,并且应该只由父级打印一次。

有人能解释一下吗?

【问题讨论】:

  • 我不确定这个,但请确保在分叉之前刷新 io-buffers。也许缓冲区被复制到孩子。
  • 这将是一个很好的面试问题!

标签: c fork stdout buffering io-redirection


【解决方案1】:

因为在reopen 之后流是非交互式的,所以它是完全缓冲的并且不会在'\n' 上刷新。在调用fork 之前,缓冲区仍然包含消息,在fork 之后,此缓冲消息被复制(因为两个进程都有自己的stdout 副本),然后由父进程和子进程刷新。请参阅 C 标准的第 7.19.3 部分。

您可以通过在fork 之前调用fflush 来避免此类行为。

【讨论】:

  • 我不知道\n 在重定向后不能用作自动刷新器。谢谢和+1
  • 你也可以使用setvbuf重新配置stdout
【解决方案2】:

这是因为缓冲。在printf 之后执行fflush

两个进程最终都得到stdio 内部内容的相同副本,并且都继续在exit 处刷新它。如果您在孩子中调用_exit,您也可能会阻止它发生。

【讨论】:

  • 如果我将exit() 更改为_exit(),则孩子不会打印任何内容。即输出中缺少I AM CHILDexit()_exit() 有什么区别?
  • @Stacker _exit 不会刷新 stdio 缓冲区。
【解决方案3】:

刷新缓冲区将解决问题。 在 print 语句之后使用 fflush。

【讨论】:

    【解决方案4】:

    似乎ERROR! WHY DONT U UNDERSTAND 在分叉后仍然被缓冲并被两个进程写入。

    如果你添加

    fflush(stdout);
    

    在您的第一个 printf() 之后立即刷新内部缓冲区,并且它仅在您的文件中出现一次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-27
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 2021-09-12
      • 1970-01-01
      • 2021-11-13
      相关资源
      最近更新 更多