2017-05-09 54 views
0

爲什麼程序打印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

回答

2

你在你的 「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」語句。

1

由於默認情況下標準輸出是行緩衝(或完全緩衝,如果將其重定向到文件或管道)。

第一個printf未找到換行符,因此它只將字符串do添加到C庫內部的緩衝區中。在第一個fork,整個過程,包括該緩衝區,是重複的。然後,其中一個副本增加了ma到緩衝區中,把兩份都被複制(因爲過程再次調用fork,不只是父母或子女)。

最後,無論是printf(" to \n ")printf("\n")被調用,產生換行符,它觸發緩衝區中任何內容的實際寫入。

您可以使用fflush(stdout)強制C庫在您分叉之前輸出任何緩衝數據,或者使用setbuf(stdout, NULL)完全禁用緩衝區。