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"); 
} 

程序打印 做马 做 做马到 做

+0

编辑,当然fork() – Klapi

你在你的 “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)完全禁用缓冲区。