C 中 fork 调用的意外输出

Unexpected output on a fork call in C

我在学校作业中遇到了这个,但它没有产生我认为应该产生的结果:

int main() {
    printf("c");
    fork();
    printf("d");
}

我知道这段代码有几处不好的地方(即 main 中没有参数,fork 中的 return 值没有变量,末尾没有 return 语句,等),但这就是它的呈现方式,无论如何它与我的问题无关。

此代码产生输出:

cdcd

据我了解,当调用 fork 时,parent 和 child 都会在 fork 调用后 resume/begin 在线。基于此,我预计输出为:

cdd

当然假设fork调用成功。任何人都可以向我解释为什么第二次打印“c”,即使它在 fork 调用之前就已经在线上了吗?

谢谢! M_MN

您看到 c 两次的原因是 fork() 复制了未打印的缓冲输出。您可以在 fork():

之前刷新输出流
fflush(stdout);

或者您可以将 stdout 设置为无缓冲,但您应该在第一次调用 printf() 之前先执行此操作:

setvbuf(stdout, NULL, _IONBF, 0);

这是我猜测的情况。 printf 写入流 stdout。由于您在打印 "c" 后没有刷新 stdout 也没有在新行中结束该字符串,因此该字符位于 user-space 缓冲区中。当您调用 fork 时,子进程获得父进程的虚拟地址 space 的副本,包括缓冲文本。当两个程序都退出时,它们的缓冲区被刷新,因此 "c" 出现了两次。

尝试在调用 fork 之前添加 fflush(stdout);

您在刷新标准输出之前分叉了您的程序(即:数据仍在输出缓冲区中)。只需调用 fflush(stdout) 来修复它:

❯ cat test.c
#include <stdio.h>
#include <unistd.h>

int main() {
    printf("c");
    fflush(stdout);
    fork();
    printf("d");
}

[22:14:01]~/devel
❯ clang test.c -o test
[22:14:07]~/devel
❯ ./test
cdd[22:14:09]~/devel