c - 如果 shell 输出通过管道传输到某处,fork() 会导致父级 main 的开头执行

标签 c unix fork

<分区>

我尝试使用 fork() 函数,但出现了一些奇怪的行为。父进程的部分(不是全部)主要函数似乎在 fork() 被调用后立即运行,但前提是可执行文件的输出通过管道传输到命令行中的某处。

我在 Mac OS Mojave 上注意到了这一点,但我在 Ubuntu 18.04 上测试了相同的代码,它表现出相同的行为。我不知道为什么会这样。

下面是fork.c文件中的测试代码:

#include <stdio.h>
#include <unistd.h>

int main(void)
{
        pid_t child_pid;
        printf("Beginning of main for process %d\n", getpid());
        if ((child_pid = fork())) {
                printf("Forked process %d\n", child_pid);
        } else {
                printf("Beginning of forked process %d\n", getpid());
        }
}

这是一个使用这段代码的 shell session :

 $ cc fork.c
 $ ./a.out
Beginning of main for process 98373
Forked process 98374
Beginning of forked process 98374
 $ ./a.out | cat
Beginning of main for process 98378
Forked process 98380
Beginning of main for process 98378
Beginning of forked process 98380

正如您在上面看到的,如果输出通过管道传输到某处,则 main() 开头的语句将在父进程中执行两次。

最佳答案

这与 I/O 缓冲有关。

控制台默认是行缓冲的,所以如果你的输出字符串以换行符结尾并且你没有重定向,输出会立即刷新。但是当您重定向 stdout 时,换行符不会刷新缓冲区。因此,当您 fork 父项和子项时,输出缓冲区中都有一行文本,因此两者都打印第一行。

您可以通过使用 fflush 显式刷新缓冲区来解决此问题。

printf("Beginning of main for process %d\n", getpid());
flush(stdout);

关于c - 如果 shell 输出通过管道传输到某处,fork() 会导致父级 main 的开头执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57135529/

相关文章:

有人可以告诉我如何创建这个非常简单的 makefile 吗?

c - 一般 Quick fork() 解释

c - 试图弄清楚 fork() 在这种情况下是如何工作的,但我似乎不明白答案是如何实现的

c - 在 C 中用 fork 搜索

c - 为什么 gcc4 不展开这个循环?

c - 关于 c 中递归的快速问题

c - execvp 因多个参数或没有参数而失败

在 C 中创建静态模块接口(interface)

c - UNIX - 列出所有现有的串行端口

linux - ubuntu 和 unix 关于目录和隐藏文件的东西