3

请看下面的代码。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{

        fork();
        printf(".");
        fflush(stdout);
        fork();
        printf(",");

   return 0;
}

输出是:

..,,,,

这对我来说没问题,

但是如果我fflush(stdout)从上面的程序中删除,那么输出应该是(根据我的理解)。

  ...,.,.,.,

is 的语句fork():紧随其后的语句fork()被复制到父级和子级中。

我的理解是:在第一个fork()之后有两个进程(假设它是进程 p 和进程 c)我们有

进程 p 和 c 中的代码是:

    printf(".");
    fork();
    printf(",");

现在,假设执行了进程 p 和 c 的第一条语句,那么输出将是 .

  ..

现在fork()语句开始执行。所以,在执行之后fork(),我们的进程就像 p , pc ,c ,cc 一样。

p , pc , c 和 cc 中的代码是

    printf(",");

我们不冲洗stdout所以printf(".")仍然存在于每个缓冲区中。

所以每个进程都会打印., 所以输出是

 .,.,.,.,

我的问题是:1)以前在哪里.. ?即根据我的解释,输出应该是

                ...,.,.,.,
4

2 回答 2

5

由于没有刷新,因此不会写入任何内容。每个forked 进程都会有“.”,准备好在第二个 之后写入printf

    fork();

我们有两个过程。

    printf(".");

他们每个人都准备好写“。”。

    fork();

我们有四个流程。

    printf(",");

他们每个人现在都准备好写“.”了。

    return 0;

当每个进程刷新时,它会将“.”写入stdout,产生最可能的输出“.,.,.,.,”。

于 2013-09-07T08:47:40.703 回答
4

如果没有刷新,每个进程(2 个分叉后总共 4 个)将缓冲它的输出,并在进程退出时打印它(我认为是由库安装的退出处理程序),因为这里的所有输出都适合缓冲区并且您不会触发刷新它们。.,因此,每个进程都将完全像对内核的一次写入一样打印。您在进程之间没有同步(例如父进程在退出之前等待子进程退出),因此顺序是不确定的,取决于内核进程调度程序的心血来潮,但由于每个进程的输出是相同的,所以输出什么并不重要:

.,.,.,.,

所以这里的关键是,对于问题代码,没有刷新,写入发生在 2 个字符的块中,不可能交错单个字符。但这当然取决于控制台的实现,可以编写一个控制台驱动程序,它总是一次只工作一个字符,然后可能会发生单个字符的交错。我这样说是为了澄清,你所看到的不是一些标准的明确定义的行为,它只是由于实现细节而发生的事情。

于 2013-09-07T08:58:04.083 回答