2012-05-22 4 views
6

Ich experimentierte mit fork() und re-direction, um zu überprüfen, ob die im Elternteil vorgenommenen Umleitungen auch für das Kind gelten. Ich schrieb das folgende einfache ProgrammStatement vor fork() zweimal drucken

#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; 
} 

Der Ausgang (error.txt) Ich habe

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

Überraschenderweise ist, ERROR! WHY DONT U UNDERSTAND? ist Druck zweimal obwohl es viel erscheint, bevor der fork() genannt wird und sollte nur einmal vom Elternteil gedruckt werden.

Kann jemand etwas Licht darauf werfen?

+0

Ich bin mir nicht sicher über diese, aber stellen Sie sicher, Sie spülen io-Puffer, vor der Gabelung. Vielleicht werden die Puffer auf das Kind kopiert. – lupz

+2

Dies würde für eine ausgezeichnete Interviewfrage sorgen! – dasblinkenlight

Antwort

10

Da der Stream nach reopen nicht interaktiv ist, ist er vollständig gepuffert und spült nicht auf '\n'. Bevor fork aufgerufen wird, enthält der Puffer immer noch die Nachricht, und nach fork wurde diese gepufferte Nachricht dupliziert (weil beide Prozesse ihre eigenen Kopien von stdout erhalten haben) und dann sowohl vom Eltern als auch vom Kind geleert. Siehe Teil 7.19.3 des C-Standards.

Sie können dieses Verhalten vermeiden, indem Sie fflush kurz vor fork aufrufen.

+0

Ich weiß nicht, dass '\ n' nach der Umleitung nicht als automatischer Flusher funktioniert. Danke und +1 –

+0

Sie könnten 'setvbuf' auch verwenden, um' stdout' zu rekonfigurieren. –

3

Es ist wegen der Pufferung. Machen Sie eine fflush direkt nach printf.

Beide Prozesse enden mit der gleichen Kopie von stdio internen Sachen und beide fahren fort, es bei zu spülen. Sie können auch verhindern, dass es passiert, wenn Sie _exit im Kind aufrufen.

+0

Wenn ich 'exit()' in '_exit()' ändere, druckt das Kind nichts. dh "ICH BIN KIND" fehlt in der Ausgabe. Was ist der Unterschied zwischen 'exit()' und '_exit()'? –

+1

@Stacker '_exit' löscht keine STDIO-Puffer. – cnicutar

1

Das Löschen des Puffers löst das Problem. Verwenden Sie fflush direkt nach der Druckanweisung.

0

Es scheint, dass die ERROR! WHY DONT U UNDERSTAND noch nach Forking gepuffert ist und von beiden Prozessen geschrieben wird.

Wenn Sie

fflush(stdout); 

direkt nach dem ersten printf() der interne Puffer gespült hinzufügen und es erscheint nur einmal in der Datei.