c - 为什么 fflush() 会影响 fork 进程的输出?

标签 c operating-system buffer fork system-calls

我正在尝试学习 UNIX 编程,遇到一个关于 fork() 的问题,我无法解释下面两个程序的输出。

我知道 fork() 创建了一个与当前正在运行的进程相同的进程,但是它从哪里开始呢?例如,如果我有下面这两个程序,输出结果是什么,它是如何工作的?

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

int main (int argc, char **argv)
{
    int retval;
    printf ("This is most definitely the parent process\n");
    // now here fork will create a child process 
    // i need to know from which line child process starts execution 

    retval = fork ();
    printf ("Which process printed this?\n");

    return (0);
}

上面的程序和下面的程序有什么区别 关于子进程执行:

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

int main (int argc, char **argv)
{
    int retval;
    printf ("This is most definitely the parent process\n");

    fflush (stdout);
    // how does fflush change the output of above program and why ?
    // even though no string operations are being used
    retval = fork ();
    printf ("Which process printed this?\n");

    return (0);
 }

我认为他们都应该打印:

This is most definitely the parent process 
Which process printed this? 
Which process printed this? 

但第一个是打印:

This is most definitely the parent process 
Which process printed this? 
This is most definitely the parent process 
Which process printed this? 

最佳答案

I understand that fork() creates an identical process of the currently running process, but where does it start?

如果 fork(2) 成功(即不返回 -1),它从调用 fork(2) 的行开始>。 fork(2) 返回两次:它在子进程中返回 0,在父进程中返回正数 C,其中 C 是进程 ID新生儿。

您两次看到 This definitely the parent process 的原因与 stdio 的缓冲有关。用户空间缓冲区中的 Stdio 缓冲区输出仅在某些情况发生时才刷新(例如,缓冲区变满)。缓冲模式决定何时以及如何刷新缓冲区。

通常,如果输出被写入交互式设备,如终端(或伪终端),stdio 是line-buffered,这意味着当找到换行符或fflush(3) 被调用。

OTOH,如果输出被重定向到文件或其他非交互式设备(例如,输出被重定向到管道),stdio 是完全缓冲,这意味着缓冲区仅被刷新当它们变满或调用 fflush(3) 时。

因此,如果没有 fflush(3),在终端设备中执行代码将打印:

This is most definitely the parent process
Which process printed this?
Which process printed this?

这是预期的。但是,如果您通过 cat(1) 对其进行管道传输,您将看到这个(或其他一些变体,取决于执行顺序):

This is most definitely the parent process
Which process printed this?
This is most definitely the parent process
Which process printed this?

这是因为输出在重定向到管道时是完全缓冲的。字符串 This is most definitely the parent process 不足以填充和刷新缓冲区,因此当父进程 fork 时,子进程(获得父进程内存空间的副本)将获得一个副本输出缓冲区,其中已经包含字符串 This is most definitely the parent process。所以这两个进程最终都会打印该字符串。

如果您总是在 fork 之前调用 fflush(3),则不会发生这种情况,因为当父级的内存空间被复制到子级时缓冲区是空的。

关于c - 为什么 fflush() 会影响 fork 进程的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32331292/

相关文章:

c - C 中字符串如何终止?

c++ - 从左侧调整大小时窗口闪烁

python - 在 Python 的 C 扩展中调用 C 函数

c# - 在 C# 中确定操作系统和处理器类型

javascript - "value"参数不能是数字

c - 打印不正确的输出

在linux机器上调用系统调用

python - 在 Python 中使用 os.rename() 重命名文件时出错

javascript - 触发textarea ctrl-z 撤消缓冲区更新

Java Paint 组件刷新率?