Ich stelle fest, dass dies <system.h>
ein nicht standardmäßiger Header ist. Ich habe es durch ersetzt <unistd.h>
und den Code sauber kompiliert.
Wenn die Ausgabe Ihres Programms an ein Terminal (Bildschirm) geht, wird es zeilengepuffert. Wenn die Ausgabe Ihres Programms an eine Pipe geht, ist sie vollständig gepuffert. Sie können den Puffermodus mit der Standard-C-Funktion setvbuf()
und den Modi _IOFBF
(vollständige Pufferung), _IOLBF
(Zeilenpufferung) und _IONBF
(keine Pufferung) steuern.
Sie können dies in Ihrem überarbeiteten Programm demonstrieren, indem Sie beispielsweise die Ausgabe Ihres Programms an Folgendes weiterleiten cat
. Selbst mit den Zeilenumbrüchen am Ende der printf()
Zeichenfolgen würden Sie die doppelte Information sehen. Wenn Sie es direkt an das Terminal senden, sehen Sie nur die eine Menge Informationen.
Die Moral der Geschichte ist es, vorsichtig zu sein, fflush(0);
um alle E / A-Puffer vor dem Gabeln zu leeren.
Zeilenweise Analyse nach Bedarf (Klammern usw. entfernt - und führende Leerzeichen vom Markup-Editor entfernt):
printf( "Hello, my pid is %d", getpid() );
pid = fork();
if( pid == 0 )
printf( "\nI was forked! :D" );
sleep( 3 );
else
waitpid( pid, NULL, 0 );
printf( "\n%d was forked!", pid );
Die Analyse:
- Kopiert "Hallo, meine PID ist 1234" in den Puffer für die Standardausgabe. Da am Ende keine neue Zeile vorhanden ist und die Ausgabe im zeilengepufferten Modus (oder im voll gepufferten Modus) ausgeführt wird, wird auf dem Terminal nichts angezeigt.
- Gibt uns zwei separate Prozesse mit genau demselben Material im Standardpuffer.
- Das Kind hat
pid == 0
und führt die Zeilen 4 und 5 aus; Das übergeordnete Element hat einen Wert ungleich Null für pid
(einer der wenigen Unterschiede zwischen den beiden Prozessen - Rückgabewerte von getpid()
und getppid()
sind zwei weitere).
- Fügt dem Ausgabepuffer des Kindes eine neue Zeile und "Ich wurde gegabelt !: D" hinzu. Die erste Ausgabezeile wird auf dem Terminal angezeigt. Der Rest wird im Puffer gehalten, da die Ausgabe zeilengepuffert ist.
- Alles hält für 3 Sekunden an. Danach verlässt das Kind normal durch die Rückkehr am Ende der Hauptleitung. Zu diesem Zeitpunkt werden die Restdaten im Standardpuffer gelöscht. Dadurch bleibt die Ausgabeposition am Ende einer Zeile, da keine neue Zeile vorhanden ist.
- Der Elternteil kommt hierher.
- Der Elternteil wartet darauf, dass das Kind mit dem Sterben fertig ist.
- Der Elternteil fügt eine neue Zeile hinzu und "1345 wurde gegabelt!" zum Ausgabepuffer. Die neue Zeile löscht die Nachricht "Hallo" nach der vom Kind generierten unvollständigen Zeile in die Ausgabe.
Das übergeordnete Element wird jetzt normal durch die Rückgabe am Ende von main beendet, und die verbleibenden Daten werden gelöscht. Da am Ende noch keine neue Zeile steht, befindet sich die Cursorposition hinter dem Ausrufezeichen und die Shell-Eingabeaufforderung wird in derselben Zeile angezeigt.
Was ich sehe ist:
Osiris-2 JL: ./xx
Hello, my pid is 37290
I was forked! :DHello, my pid is 37290
37291 was forked!Osiris-2 JL:
Osiris-2 JL:
Die PID-Nummern sind unterschiedlich - aber das allgemeine Erscheinungsbild ist klar. Das Hinzufügen von Zeilenumbrüchen am Ende der printf()
Anweisungen (was sehr schnell zur Standardpraxis wird) verändert die Ausgabe erheblich :
#include <stdio.h>
#include <unistd.h>
int main()
{
int pid;
printf( "Hello, my pid is %d\n", getpid() );
pid = fork();
if( pid == 0 )
printf( "I was forked! :D %d\n", getpid() );
else
{
waitpid( pid, NULL, 0 );
printf( "%d was forked!\n", pid );
}
return 0;
}
Ich bekomme jetzt:
Osiris-2 JL: ./xx
Hello, my pid is 37589
I was forked! :D 37590
37590 was forked!
Osiris-2 JL: ./xx | cat
Hello, my pid is 37594
I was forked! :D 37596
Hello, my pid is 37594
37596 was forked!
Osiris-2 JL:
Beachten Sie, dass die Ausgabe, wenn sie an das Terminal gesendet wird, zeilengepuffert ist, sodass die Zeile "Hallo" vor dem angezeigt wird fork()
und nur eine Kopie vorhanden war. Wenn die Ausgabe an weitergeleitet wird, cat
ist sie vollständig gepuffert, sodass vor dem fork()
und beide Prozesse die Zeile "Hallo" im zu löschenden Puffer angezeigt wird.