fork()移至main()的开头

时间:2018-12-19 00:33:56

标签: fork

我有以下代码:

#include <stdio.h>

int main() {
    printf("Hello\n");
    fork();
    return 0;
}

这给出了输出:

Hello

符合预期。但是,如果我将代码修改为:

#include <stdio.h>

int main() {
    printf("Hello");
    fork();
    return 0;
}

删除,\ n提供输出:

HelloHello

为什么printf被调用两次。子进程是否不应该执行下一条指令:return 0;

2 个答案:

答案 0 :(得分:3)

printf函数调用将hello字符放入与stdout流相关联的缓冲区中。随后,当进程退出时(即我们看到输出时),将刷新缓冲区。您已经在此发生之前分叉了,因此当两个进程各自退出时,两个进程将在两个单独的地址空间中执行此缓冲区刷新。每个进程都有一个流的副本,其中包含缓冲区及其hello内容。

stdout流连接到交互式设备(如Unix上的TTY)时,将对其进行行缓冲。行缓冲意味着每当输出换行符时都会刷新缓冲区。

如果我们在fork之前刷新缓冲区(例如通过打印换行符或通过调用fflush(stdout)),则刷新将在父进程中进行。 fork时缓冲区为空;尽管子进程继承了它的副本,但是在任何一个进程中都没有刷新的对象。

在输出重复的情况下,实际上 被调用了两次。它不是printf,而是write系统调用,它将缓冲的字符发送到输出设备。

答案 1 :(得分:1)

它没有被两次调用。请记住,默认情况下,与控制台连接的stdout是行缓冲的。由于您还没有用换行符结束printf参数,因此它不会进入控制台。它只会先进入缓冲区。因此,printf("Hello");"Hello"复制到输出缓冲区中,fork()使用地址空间的副本(包括stdout的输出缓冲区和{{ 1}}中的字符串)和"Hello"将控制权返回给return 0;,这将刷新输出缓冲区,但是由于这是在libc之后发生的,因此它将发生两次-一次父级,一次进入子级,因此最终输出中将得到fork()