【问题标题】:How does fork() work with buffered streams like stdout? [duplicate]fork() 如何处理像 stdout 这样的缓冲流? [复制]
【发布时间】:2013-09-11 08:46:25
【问题描述】:

请看下面的代码。

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

int main(void)
{

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

   return 0;
}

输出是:

..,,,,

这对我来说没问题,

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

  ...,.,.,.,

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)以前的..在哪里? 即根据我的解释,输出应该是

                ...,.,.,.,

【问题讨论】:

  • 所以您希望. 已经被打印,但同时还在缓冲区中?还是我误解了你的期望?
  • 你应该总是保持fork(2)pid_t result并且你应该处理三种情况:失败(结果为-1) ,父母成功(结果是孩子的积极pid),孩子成功(结果为0)。
  • 阅读像 Advanced Linux Programming 这样的好书 - 其中有一整章关于流程 - 以及 fork system call 上的维基页面
  • @hvd :是的,. 应该打印在终端上,并且由于我不刷新 stdout ,它应该仍然在缓冲区中(根据我的理解)。
  • 在没有任何锁定或同步的情况下,四个进程之间的输出顺序并不是完全确定的。虽然调度程序通常会公平竞争,但您几乎无法控制它的作用以及可能影响它的其他系统事件。例如,以不同优先级运行的其他进程。假设这些不同分叉进程的输出顺序是不明智的。

标签: c linux


【解决方案1】:

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

    fork();

我们有两个进程。

    printf(".");

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

    fork();

我们有四个流程。

    printf(",");

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

    return 0;

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

【讨论】:

  • 你的意思是说,如果我不刷新缓冲项,它们就会被覆盖?
  • 不,没有任何内容被覆盖。缓冲区刚刚添加到。
【解决方案2】:

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

.,.,.,.,

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-11
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 2012-10-03
    相关资源
    最近更新 更多