2012-05-22 77 views
6

我正在試驗fork()並重新檢查是否在父項中重做的方向也適用於孩子。我寫了下面的簡單程序fork()打印兩次之前的聲明

#include<stdio.h> 
#include<unistd.h> 
#include<stdlib.h> 

int main() 
{ 
    freopen("error.txt", "w+t", stdout); // From now on, stdout = error.txt 
    printf (" ERROR! WHY DONT U UNDERSTAND?\n"); 
    if (fork() == 0) 
    { 
     printf(" I AM CHILD\n"); 
     exit(0); 
    } 
    else- 
    { 
     printf (" EITHER I AM A PARENT OR SOMETHING GOT SCREWED\n"); 
    } 


    return 0; 
} 

輸出(error.txt)我是

ERROR! WHY DONT U UNDERSTAND? 
EITHER I AM A PARENT OR SOMETHING GOT SCREWED 
ERROR! WHY DONT U UNDERSTAND? 
I AM CHILD 

出人意料的是,ERROR! WHY DONT U UNDERSTAND?打印兩次fork()被調用,應該即使它看起來多少隻能由父母打印一次。

任何人都可以對此有所瞭解嗎?

+0

我不確定這個,但確保你在fork之前刷新io-buffers。也許緩衝區被複制到孩子。 – lupz

+2

這將成爲一個優秀的面試問題! – dasblinkenlight

回答

10

由於在reopen之後該流是非交互式的,因此它是完全緩衝的,並且在'\n'上沒有刷新。在調用fork之前,緩衝區仍包含消息,並且在fork之後,此緩衝消息被複制(因爲兩個進程都獲得了自己的stdout副本),然後由父級和子級刷新。參見C標準的第7.19.3部分。

您可以通過在fork之前撥打fflush來避免此類行爲。

+0

我知道'\ n'在重定向後不能用作自動沖洗器。謝謝,+1 –

+0

你也可以使用'setvbuf'來重新配置'stdout'。 –

3

這是因爲緩衝。在printf之後執行fflush

這兩個過程最終都會得到stdio的內部副本,並且都會在exit處進行刷新。如果您在小孩中撥打_exit,您也可以防止它發生。

+0

如果我將'exit()'更改爲'_exit()',那麼孩子不會打印任何東西。即輸出中缺少'I AM CHILD'。 'exit()'和'_exit()'有什麼區別? –

+1

@Stacker'_exit'不刷新stdio緩衝區。 – cnicutar

1

沖洗緩衝區將解決問題。 在打印語句後面使用fflush。

0

似乎ERROR! WHY DONT U UNDERSTAND仍然在分叉後被緩衝,並被兩個進程寫入。

如果您的權利後,你的第一printf()內部緩衝區被刷新,而且只在您的文件中出現一次加

fflush(stdout);