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