考虑以下代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
int i;
for(i = 0; i < 2; i++)
{
fork();
printf(".");
}
return 0;
}
这个程序输出了8个点。这怎么可能呢?难道不应该是6个点吗?
考虑以下代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
int i;
for(i = 0; i < 2; i++)
{
fork();
printf(".");
}
return 0;
}
这个程序输出了8个点。这怎么可能呢?难道不应该是6个点吗?
fork()
原语常常让人感到困惑。 在您了解它之前,应在纸上跟踪每个操作并记录进程数量。 不要忘记fork()
会创建当前进程的一个近乎完全相同的副本。 对于大多数目的而言,最显着的区别在于fork()
的返回值在父进程和子进程之间不同。(由于此代码忽略返回值,因此这没有影响。)printf()
真正做的是缓冲其输出。 因此,当只有两个进程时的第一个点在写入时不会出现。 这些点保留在缓冲区中,并在fork()
时复制。 直到该进程即将退出时,缓冲的点才会出现。 四个进程打印一个缓冲的点,再加上新的点,总共有8个点。printf()
之后调用fflush(stdout);
。fork()
函数并不会创建两个进程然后退出,它只会创建一个新的进程。 - Izkata你的输出流中有未提交的缓冲区。stdout是行缓冲的,并且该缓冲区会随着进程的其余部分一起复制。当程序终止时,这个未提交的缓冲区将被写入两次(每个进程写入一次)。双方都使用。
printf("a\n");
并且
printf("a "); fflush(stdout);
在您的第一个示例中,您创建了四个进程,每个进程的输出流缓冲区中都有两个点。当每个流终止时,它会刷新其缓冲区,生成八个点。
不要展示这个问题。
当 i=0 时
进程 1:缓冲文本= 1 个点
进程 2(由进程 1 创建):缓冲文本= 1 个点
当 i=1 时
进程 3(由进程 1 创建):从进程 1 继承 1 个缓冲点并自己打印 1 个点。进程 3 总共打印 2 个点。
进程 4(由进程 2 创建):从进程 2 继承 1 个缓冲点并自己打印 1 个点。进程 4 总共打印 2 个点。
进程 1:打印 2 个点(i=0 时有一个缓冲点和 i=1 时的另一个点)
进程 2:打印 2 个点(i=0 时有一个缓冲点和 i=1 时的另一个点)
最终输出:8 个点。 :)