为什么程序打印 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");
}
程序打印做马做做马到do to
你在 "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 两次。
因为标准输出默认是行缓冲的(或者完全缓冲,如果将其重定向到文件或管道(。
第一个printf
不命中换行符,因此它仅将字符串do
添加到 C 库内部的缓冲区。在第一个fork
,整个过程,包括那个缓冲区,是重复的。然后,其中一个副本将ma
添加到其缓冲区,并且两个副本都是重复的(因为两个进程都再次调用fork
,而不仅仅是父进程或子进程。
最后,调用 printf(" to n ")
或 printf("n")
,生成换行符,触发缓冲区中任何内容的实际写入。
可以使用 fflush(stdout)
强制 C 库在分叉之前输出任何缓冲数据,也可以使用 setbuf(stdout, NULL)
完全禁用缓冲。