fork() 复制 printf() 输出

Use*_*ser 1 c linux fork

我刚刚学习如何在 C 中使用 fork(),但在理解执行流程时遇到了困难。

代码:

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

int main() {
    printf("starting...\n");

    int x = 100;

    int rc = fork();

    if (rc < 0) {
        printf("unable to fork\n");
        exit(-1);
    } else if (rc == 0) {
        x = x + 200;
        printf("child x == %d\n", x);
    } else {
        x = x + 500;
        printf("parent x == %d\n", x);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

按照您的预期执行:

user@fedora> ./main
starting...
parent x == 600
child x == 300
Run Code Online (Sandbox Code Playgroud)

当我从以下位置删除 \n 时,奇怪的事情发生了printf("starting...\n");

user@fedora> ./main
starting...parent x == 600
starting...child x == 300
Run Code Online (Sandbox Code Playgroud)

为什么当我删除\n“开始...”打印两次时,它显然不应该?

请您解释一下为什么在这种情况下printf("starting...")执行两次?

谢谢你!

小智 5

您的问题不在于 fork 系统调用;而是在于 fork 系统调用。相反,它与 C 的常见 I/O 操作的缓冲方式有关。

在 C 中,printf()函数并不总是输出到终端。相反,它写入缓冲区,当缓冲区被刷新时,终端实际上​​被写入。当打印换行符 '\n'、缓冲区已满或使用 手动刷新缓冲区时,通常会发生这种情况fflush(stdout)

当从初始 printf() 语句中删除 n 时,“starting...”字符串将写入代码中的缓冲区,但不会立即刷新到终端。

当 fork() 函数执行时,整个过程(包括未刷新的缓冲区)将被复制。这表明“正在启动...”现在出现在父进程和子进程的输出缓冲区中。

终止进程中任何未刷新的输出都会自动刷新。因此,对于每个过程,“starting...”都会打印两次。

将 n 保留在初始printf()指令中或在调用 fork() 之前手动刷新缓冲区是解决此问题的两种方法:

printf("starting...");
fflush(stdout);
Run Code Online (Sandbox Code Playgroud)