为什么 main 被调用两次?

Why is main called twice?

我刚刚了解了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。

正在缓冲。 Printf(通常)不会向标准输出写入任何内容。它只是更新一些内部数据结构。这些数据结构在 child 中重复,当流被刷新时,数据被写入。在分叉之前你应该 flush(stdout)

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

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

在这种情况下。父 PID 的标准输出缓冲区在 fork 期间被复制到子 PID。然后,父进程和子进程都在终止之前写入它们的缓冲区。这会导致打印重复数据。

Here 是一个 ideone link,在调用 fork() 之前包含 fflush(stdout);

问题来自缓冲。当 stdout 不与终端关联时,它不是行缓冲的。您写入的字符串足够短,可以保留在缓冲区中,并且仅在程序终止时才写出。因此,您首先会看到进程 27380 正在转储其缓冲区,然后是进程 27383 正在转储其缓冲区。 27380: Common code1 行在 fork 之前没有被清除,所以它在原始进程和 forked 进程的缓冲区中。在分叉之前调用 fflush() 来解决这个问题。