“fork()”之后的printf异常

“fork()”之后的printf异常

操作系统:Linux,语言:纯C

我正在学习一般的C编程,以及UNIX下的特殊情况下的C编程。

我发现了一种奇怪的行为printf()函数在使用fork()打电话。

电码

#include <stdio.h>#include <system.h>int main(){
    int pid;
    printf( "Hello, my pid is %d", getpid() );

    pid = fork();
    if( pid == 0 )
    {
            printf( "\nI was forked! :D" );
            sleep( 3 );
    }
    else
    {
            waitpid( pid, NULL, 0 );
            printf( "\n%d was forked!", pid );
    }
    return 0;}

输出量

Hello, my pid is 1111I was forked! :DHello, my pid is 11112222 was forked!

为什么第二个“Hello”字符串出现在子程序的输出中?

是的,这正是父母在开始时打印的,父母的pid.

但!如果我们把\n字符在每个字符串的末尾,我们得到预期的输出:

#include <stdio.h>#include <system.h>int main(){
    int pid;
    printf( "Hello, my pid is %d\n", getpid() ); // SIC!!

    pid = fork();
    if( pid == 0 )
    {
            printf( "I was forked! :D" ); // removed the '\n', no matter
            sleep( 3 );
    }
    else
    {
            waitpid( pid, NULL, 0 );
            printf( "\n%d was forked!", pid );
    }
    return 0;}

输出量:

Hello, my pid is 1111I was forked! :D2222 was forked!

为什么会发生这种事?它是正确的行为,还是一个错误?


12345678_0001
浏览 807回答 3
3回答

繁星淼淼

原因是如果没有\n在格式字符串的末尾,该值不会立即打印到屏幕上。相反,它是在进程中缓冲的。这意味着它实际上是在分叉操作之后才被打印出来的,因此您需要打印两次。添加\n虽然强制缓冲区被刷新并输出到屏幕上。这种情况发生在分叉之前,因此只打印一次。您可以通过使用fflush方法。例如printf(&nbsp;"Hello,&nbsp;my&nbsp;pid&nbsp;is&nbsp;%d",&nbsp;getpid()&nbsp;);fflush(stdout);

慕娘9325324

fork()有效地创建流程的副本。如果,在打电话之前fork(),它具有缓冲的数据,父数据和子数据都将具有相同的缓冲数据。下一次,当它们中的每一个做一些事情来刷新它的缓冲区时(例如,在终端输出的情况下打印换行符),您将看到除了该进程产生的任何新输出之外,缓冲的输出。因此,如果要在父级和子级中同时使用stdio,那么您应该fflush在分叉之前,要确保没有缓冲的数据。通常,孩子只被用来调用exec*功能。因为这取代了完整的子进程映像(包括任何缓冲区),所以在技术上没有必要fflush如果这真的是你要在孩子身上做的所有事情。但是,如果可能有缓冲的数据,那么在处理EXEC失败时应该小心。特别是,避免使用任何stdio函数将错误打印到stdout或stderr(write),然后打电话给_exit(或_Exit)而不是打电话exit或者只是返回(这将刷新任何缓冲输出)。或者用叉子前冲一下来避免这个问题。
打开App,查看更多内容
随时随地看视频慕课网APP