请看下面的代码。
#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)以前哪里? 即根据我的解释输出应该是
...,.,.,.,
由于没有冲水,没有什么会被写入。 每个forked进程都将有“。”准备在第二个printf
之后写入。
fork();
我们有两个过程。
printf(".");
他们每个人都准备写“。”。
fork();
我们有四个进程。
printf(",");
他们每个人现在都准备写“。”。
return 0;
当每个进程刷新时,它将“。”写入stdout
,产生最可能的输出“。,。,。,”。
如果没有刷新,每个进程(总共4个2叉)会缓冲它的输出,并在进程退出时打印它(由库安装的退出处理程序,我认为),因为这里的所有输出都适合缓冲区,并且不会触发刷新它们。 所以每个进程都会打印出来.,
就像写入内核一样。 你在进程之间没有同步(比如在退出之前等待子进程退出的父进程),所以进程是未定义的,直到内核进程调度器的意愿,但是由于每个进程的输出是一样的,所以输出是无关紧要的:
.,.,.,.,
所以这里最关键的是,在问题代码中,没有冲突,写入发生在2个字符的块中,不可能交织个别字符。 但是这当然取决于控制台的实现,而且可以编写一个控制台驱动程序,它一次只能处理一个字符,然后可能会发生各个字符的交错。 我只是想说明一下,你所看到的并不是一些标准的明确定义的行为,而是因为实现细节而发生的事情。