C fork()作为循环条件语句

C fork()作为循环条件语句,c,fork,C,Fork,我有下面的一段代码,我想解释这段代码中fork调用的行为,break条件作为命令行参数给出 #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { int i = 0; char *ptr; int x = strtol(argv[1], &ptr, 10); while (fork())

我有下面的一段代码,我想解释这段代码中fork调用的行为,break条件作为命令行参数给出

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

int main(int argc, char *argv[])
{
    int i = 0;
    char *ptr;
    int x = strtol(argv[1], &ptr, 10);
    while (fork())
    {
        if (i == x)
        {
            break;
        }
        printf("PID: %d, PPID: %d, i = %d\n", getpid(), getppid(), i++);
    }
    return 0;
}
我认为应该发生的是,fork调用将执行一次,创建子进程和父进程,将非零进程id返回给父进程,将零返回给子进程。 零值应解释为false,并且只有父进程将继续打印一次,然后将i的值增加到1,然后再次重复创建另一个子进程,该子进程将再次不进入循环,并且当i=1时,它将跳出循环,那么为什么我看到的是2行而不是1行? 更高的i值的输出更令人费解,但可以预见。
有人能解释一下我的假设中的缺陷吗?

您看到的重复消息来自stdio缓冲,而且printf在默认情况下并不实际打印-它只是将一些内容放入缓冲区,稍后在进程退出时刷新缓冲区时打印,如果不是之前,则从显式刷新或缓冲区填充开始

最重要的是,当您分支一个子级时,该子级将获得所有父级状态(包括所有stdio缓冲区)的副本。因此,如果在stdio缓冲区中有任何未刷新的数据,那么这些数据将被复制并最终写入两次—一次由父级写入,一次由子级写入

您可以通过放置一个显式的fflushstdout来避免这种情况;在printf之后


使这一点更加复杂的是,stdio还支持称为行缓冲模式的东西,在这种模式下,它将在每次写入换行时自动刷新文件。在某些系统上,这是在标准输出上默认设置的,但在其他系统上,它是由实现定义的。您可以通过使用setLineBufstOut在标准输出上显式设置行缓冲模式来利用这一点;在主函数的开头。

您看到的重复消息来自stdio缓冲,而且printf在默认情况下并不实际打印-它只是将一些内容放入缓冲区,稍后在进程退出时刷新缓冲区时打印,如果不是之前,则从显式刷新或缓冲区填充开始

最重要的是,当您分支一个子级时,该子级将获得所有父级状态(包括所有stdio缓冲区)的副本。因此,如果在stdio缓冲区中有任何未刷新的数据,那么这些数据将被复制并最终写入两次—一次由父级写入,一次由子级写入

您可以通过放置一个显式的fflushstdout来避免这种情况;在printf之后

使这一点更加复杂的是,stdio还支持称为行缓冲模式的东西,在这种模式下,它将在每次写入换行时自动刷新文件。在某些系统上,这是在标准输出上默认设置的,但在其他系统上,它是由实现定义的。您可以通过使用setLineBufstOut在标准输出上显式设置行缓冲模式来利用这一点;在你的主要职能的开始

PID: 684067, PPID: 14913, i = 0
PID: 684067, PPID: 14913, i = 0