为什么主叫两次?

时间:2015-01-26 10:01:06

标签: c fork

我刚学会了fork,据我所知,子进程从fork调用开始执行(否则fork会递归?)。

但是在此代码中(ideone link):

int main() {
  printf("%d: Common code1\n", getpid());
  if (fork() != 0) {
    printf("%d: Parent code\n", getpid());
  } else {
    printf("%d: Child code\n", getpid());
  }
  printf("%d: Common code\n", getpid());
}

输出结果为:

27380: Common code1
27380: Parent code
27380: Common code
27380: Common code1
27383: Child code
27383: Common code

我不明白为什么打印第4行?我可以理解它是否是从子进程打印出来的,而fork是从main打印出来的,但它是从父进程打印出来的,而fork并没有调用main。

3 个答案:

答案 0 :(得分:8)

好问题!起初我有点困惑。

使用printf时,输出会被缓冲。这意味着printf打印的内容实际上不会被刷新到控制台,直到达到换行符,或者甚至直到程序终止,如果重定向stdout。

在这种情况下。在fork期间,父PID的stdout缓冲区被复制到子节点。然后,父节点和子节点在终止之前写入其缓冲区。这会导致打印重复的数据。

Herefflush(stdout);被调用之前包含fork()的ideone链接。

答案 1 :(得分:3)

问题来自缓冲。当stdout未与终端关联时,它不是行缓冲的。您编写的字符串足够短,可以保留在缓冲区内,只有在程序终止后才会写出来。因此,您首先看到进程27380转储其缓冲区,然后处理27383转储其缓冲区。行27380: Common code1在fork之前没有被刷新,因此它位于原始进程和分叉进程的缓冲区中。在解决此问题之前立即致电fflush()

答案 2 :(得分:2)

缓冲。 Printf没有(通常)向stdout写任何东西。它只是更新了一些内部数据结构。这些数据结构在子进程中重复,当刷新流时,将写入数据。在你分叉前你应该flush(stdout)