省略或离开" \ n"打印" Hello world"两次使用fork()

时间:2014-04-20 06:15:23

标签: c process fork

我在linux上使用gcc编译器。

当我运行此代码时(注意" \ n"在printf中的hello world之后不存在)

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    printf("Hello world");
    fork();
}

我获得了这个输出:Hello worldHello world

另一方面 当我运行此代码时(注意&#34; \ n&#34;在printf中的hello world之后出现)

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    printf("Hello world\n");
    fork();
}

我获得了这个输出:Hello world

有人可以详细描述,为什么省略或离开&#34; \ n&#34;打印&#34; Hello world&#34;两次?

3 个答案:

答案 0 :(得分:3)

要详细说明链接问题中的答案并将其与您的问题联系起来,stdout通常会缓冲输入,直到看到\n,或者您明确fflush它。

如果你有\n,那么你就会在fork()之前进行冲洗。 没有\n,它会在之后刷新,因此它将存在于两个进程中。

在关联的问题中,他们谈论的是fflush(),但\n具有导致stdout刷新的相同效果。

您只会看到以下程序的一个打印件:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    printf("Hello world");
    fflush(stdout);
    fork();
}

编辑:由于来自Dabo的评论,如果\n处于线缓冲模式而不是完全缓冲模式,stdout将仅导致刷新。我们可以在以下程序中观察到,当使用setvbuf启用完全缓冲模式时,即使使用\n,我们仍会看到两次打印的字符串。

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    setvbuf(stdout, NULL,_IOFBF, BUFSIZ);
    printf("Hello world\n");
    fork();
}

输出:

Hello world
Hello world

答案 1 :(得分:1)

没有\n意味着&#34;你好世界&#34;仍然在记忆中 - 准备好以愉快的方式去终点站。

fork将复制此内存 - 即现在您有两个具有相同&#34; hello world&#34;在记忆中。当程序终止时,它将刷新到stdout。即得到它两次。

但是如果你把\n放进去 - 它会立即刷新到stdout。因此,在调用fork之前,此缓冲区将为空。

答案 2 :(得分:0)

我想说两个版本都不正确。当调用atexit时,C运行时将注册exit()个处理程序以刷新标准缓冲区。导致程序只打印一次的正确方法是在子进程中调用_exit(0);。这样你的孩子就不会打电话给atexit(这反过来又赢了两次冲洗缓冲区)

if (fork() == 0)
    _exit(0);