Fork()linux问题

时间:2017-05-09 14:19:08

标签: linux fork

为什么程序打印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");
}

程序打印 做什么 做 做到了 做到

2 个答案:

答案 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)完全禁用缓冲。