在C中使用printf()和fork()复制输出 [英] Duplicated output using printf() and fork() in C

查看:79
本文介绍了在C中使用printf()和fork()复制输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我运行了这个小程序来测试 fork(),但我无法弄清楚输出,该程序的代码是:

I run this small program to test fork(), and I can't figure out the output, the program's code is:

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

int i = 0;
void create()
{
    fork();
    printf("Inside i= %d \n", i);
    i = i + 1;
    fork();
}
int main()
{
    create();  
    return 0;
}

输出为:

Inside i= 0 
Inside i= 0 
Inside i= 0 
Inside i= 0 

不是应该只有两个输出,因为在最后一个 fork()中,孩子们没有什么可打印的了?

Aren't there supposed to be just two outputs, because in the last fork(), the children has nothing to print out?

我已经了解到,虽然最后一个子进程似乎已经执行了 printf()指令,但流程子进程将在 fork()之后执行下一条指令.

I've read that the process child will execute the next instruction, after the fork(), though the last children seems to have executed the printf() instruction.

推荐答案

程序的输出高度依赖于实现.

The output of your program is highly implementation dependent.

C标准库将缓冲应用于输出流.这意味着它将积累要写入的字符,直到缓冲区达到特定长度(或满足特定条件)为止,然后立即输出所有文本.

The C standard library applies buffering to the output stream. This means that it accumulates characters to write until the buffer reaches a certain length (or until a certain condition is met), and then outputs all the text at once.

最常见的行为是使用行缓冲,这意味着当遇到换行符( \ n )时,文本将被打印出来.这确实是您的示例在我的机器上发生的情况.因为您在 printf()之前 fork(),所以有两个进程执行该调用,并且由于存在换行符,因此将立即打印输出:

The most common behavior is to use line buffering, which means that the text will be printed out when a newline character (\n) is encountered. This is indeed what happens on my machine with your example. Since you fork() before the printf(), two processes execute the call and the output is immediately printed since there is a newline:

$ ./prog
Inside i= 0
Inside i= 0

然后在两个进程中的每个进程上执行另一个 fork(),但是由于内部输出缓冲区已被清空,因此没有更多可打印的内容,因此在这种情况下没有发生任何明显的事情

The other fork() is then executed on each of the two processes, but there's nothing more to print out, since the internal output buffer has already been emptied, so nothing noticeable happens in this case.

但是,根据您的特定实现和程序运行的条件, printf()(通常是任何 stdio 函数)可以决定采用不同的方法.缓冲规则.

However, depending on your specific implementation and the conditions in which the program is run, printf() (and in general any stdio function) could decide to apply different buffering rules.

例如,在将输出传递到另一个程序或文件时,glibc通常使用固定大小的缓冲区,并且不进行行缓冲.由于缓冲区中未填充单个短的 printf(),因此文本将保留在其中,以便稍后打印.当您第二次时,每个新的子代都获得该缓冲区的副本,然后在该过程退出时(由每个子代)打印所有文本.在我的系统上,进行管道传输时,这是输出:

For example, when piping the output to another program or to a file, glibc usually uses a fixed size buffer and does not do line buffering. Since the buffer is not filled with a single short printf(), the text is retained inside it to be printed later. When you fork() a second time, each of the new children gets a copy of said buffer, and all the text is then printed (by each one of them) when the process exits. On my system, when piping, this is the output:

$ ./prog | cat
Inside i= 0
Inside i= 0
Inside i= 0
Inside i= 0

如果要确保立即打印文本,可以使用

If you want to make sure the text is printed right away, you can either use fflush() or disable buffering of stdout with setvbuf().

示例:

  • 使用 fflush():

void create()
{
    fork();
    printf("Inside i= %d \n", i);
    fflush(stdout);
    i = i + 1;
    fork();
}

  • 使用 setvbuf():

    int main()
    {
        setvbuf(stdout, NULL, _IONBF, 0);
        create();  
        return 0;
    }
    

  • 这篇关于在C中使用printf()和fork()复制输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆