【问题标题】:confusing behaviour of fork() system call in cc 中 fork() 系统调用的令人困惑的行为
【发布时间】:2016-07-20 10:36:22
【问题描述】:

我正在检查 fork 系统调用的行为。我执行了以下程序。

#include<stdio.h>
int count=0;
int main()
{
int i;
int n=3;
for(i=1;i<=n;++i)
{
printf(" %d ",i);
fork();
} 
}

我有一个想法,在 for loop 中包含 fork() 类似于串联编写它,即

for(i=1;i<=3;i++)
   fork();

类似于

fork();
fork();
fork();

我尝试为相同的内容绘制递归树

我预计输出是八个连续的 3。但输出如下:

 1  2  3  1  2  3  1  2  3  1  2  3  1  2  3  1  2  3  1  2  3  1  2  3

注意:在gcc中编译执行

【问题讨论】:

  • 我认为如果每次调用都刷新标准输出行缓冲区,您可能会发现输出有点不同。它应该包含一个 1、两个 2 和四个 3。
  • 涉及输出缓冲

标签: c fork


【解决方案1】:

首先,您的期望是错误的,您将获得的不仅仅是 3 的输出。其次,您的stdout 行缓冲区在您分叉时被保留,因此会将先前的printf-ed 内容复制到分叉的进程中,作为进程副本的一部分。您的程序的修改版本如下:

#include <stdio.h>
#include <unistd.h>
int main()
{
    int i;
    for(i=1;i<=3;++i)
    {
        printf("%d ", i);
        fflush(stdout);
        fork();
    }
}

将产生与以下内容相似的输出:

1 2 3 2 3 3 3 

添加的刷新会在 fork 之前清空当前进程的 stdout 行,从而消除复制输出。顺序可能略有不同,但总是以1 开头,以3 结尾,此外,任何1 后面总是至少有一个2,任何2 后面总是至少有一个2一个3

【讨论】:

    【解决方案2】:

    它会这样打印
    1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
    因为父母1次,孩子1次。 Fork() :- 用于父母和孩子。

    所以循环旋转了 4 次

    1 2 3 为父母 1 2 3 为孩子

    2(父子) * 4(循环旋转) = 打印 8 次 (1 2 3)

    【讨论】:

      【解决方案3】:

      以前有人问过这个问题。你可以在这里找到类似的问题。

      Visually what happens to fork() in a For Loop

      希望对你有帮助^^

      【讨论】:

        【解决方案4】:

        因为stdout的输出默认是缓冲的,分叉进程会导致复制缓冲区,当每个进程完成时,每个缓冲区都会被刷新。

        使用:

        fprintf(stderr," %d ",i);
        

        将使程序输出:

        1 2 2 3 3 3 3
        

        因为您正在循环中制作 printf 语句(从 1 到 3)

        以下语句将帮助您跟踪输出:

        fprintf(stderr," %d:%d ",i,getpid());
        

        将输出(示例):

        1:24100  2:24100  2:24101  3:24100  3:24102  3:24101  3:24103
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-11-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-22
          相关资源
          最近更新 更多