Fork()linux问题
问题描述:
为什么程序打印4次'do'而不是'do'?Fork()linux问题
代码:
#include<stdio.h>
#include<unistd.h>
int main()
{
printf(" do ");
if(fork()!=0) printf(" ma ");
if(fork()==0) printf(" to \n ");
else printf("\n");
}
程序打印 做马 做 做马到 做
答
你在你的 “if” 语句两次调用fork:
if(fork()!=0) printf(" ma ");
if(fork()==0) printf(" to \n ");
在第一个fork,父A生成一个子B,然后父和子都会调用fork a 第二次。父母会产生孩子C,孩子会产生孩子D.结果是4个过程:A,B,C,D。
A ---- B
| |
C D
由于您的打印件缓冲,直到刷新到标准输出和每个分叉过程得到这个缓冲区的副本,四“不要”打印(检查@ilkkachu答案)。
如果你打算有一个“做”,你应该这样做,而不是:
pid_t pid = fork();
if (pid > 0){
printf(" do ");
printf(" ma ");
} else {
printf(" to \n");
}
基本上两次存储叉()的一个变量而不是调用fork返回你的“if”语句。
答
由于默认情况下标准输出是行缓冲(或完全缓冲,如果将其重定向到文件或管道)。
第一个printf
未找到换行符,因此它只将字符串do
添加到C库内部的缓冲区中。在第一个fork
,整个过程,包括该缓冲区,是重复的。然后,其中一个副本增加了ma
到缓冲区中,把两份都被复制(因为都过程再次调用fork
,不只是父母或子女)。
最后,无论是printf(" to \n ")
或printf("\n")
被调用,产生换行符,它触发缓冲区中任何内容的实际写入。
您可以使用fflush(stdout)
强制C库在您分叉之前输出任何缓冲数据,或者使用setbuf(stdout, NULL)
完全禁用缓冲区。
编辑,当然fork() – Klapi