Warum druckt dieses Programm 4 mal "gabeled"?

76

Warum druckt dieses Programm "gegabelt!" 4 mal?

%Vor%     
rona-altico 03.11.2014, 14:30
quelle

6 Antworten

82

Der erste fork() gibt einen Wert ungleich Null im aufrufenden Prozess zurück (nennen Sie ihn p0) und 0 im untergeordneten Code (nennen Sie ihn p1).

In p1 wird der Kurzschluss für && genommen und der Prozess ruft printf auf und wird beendet. In p0 muss der Prozess den Rest des Ausdrucks auswerten. Dann ruft es fork() erneut auf und erstellt so einen neuen untergeordneten Prozess (p2).

In p0 fork() gibt einen Wert ungleich null zurück, und der Kurzschluß für || wird genommen, so daß der Prozeß printf aufruft und endet.

In% 2 gibt fork() 0 zurück, so dass der Rest von || muss ausgewertet werden, welches ist das letzte fork() ; das führt zur Schaffung eines Kindes für p2 (nennen Sie es p3).

P2 führt dann printf aus und endet.

P3 führt dann printf aus und endet.

4 printf s werden dann ausgeführt.

    
Jean-Baptiste Yunès 03.11.2014, 14:46
quelle
195

Die eine kommt aus main() und die anderen drei aus jeder fork() .

Beachten Sie, dass alle drei forks() ausgeführt werden. Vielleicht möchten Sie sich die Referenz ansehen:

  

RÜCKGABEWERT

     

Nach erfolgreicher Beendigung gibt fork () 0 an den untergeordneten Prozess zurück und muss die Prozess-ID des untergeordneten Prozesses an den übergeordneten Prozess zurückgeben. Beide Prozesse sollen weiterhin von der Funktion fork () ausgeführt werden. Andernfalls wird -1 an den übergeordneten Prozess zurückgegeben, kein untergeordneter Prozess muss erstellt werden, und errno muss so eingestellt werden, dass der Fehler angezeigt wird.

Beachten Sie, dass die Prozess-ID nicht null sein kann, wie hier .

Was passiert wirklich?

Wir haben:

%Vor%

Also wird das erste fork() zu der Eltern-Prozess-ID zurückgeben, die nicht Null ist, während es 0 an den Kind-Prozess zurückgibt. Das bedeutet, dass der erste Fork des logischen Ausdrucks im Parent-Prozess als true ausgewertet wird, während er im Child-Prozess als false und aufgrund von Kurzschlussauswertung , die restlichen zwei fork() s werden nicht aufgerufen.

Also, jetzt wissen wir, dass wir mindestens zwei Abzüge bekommen werden (einen von der Haupt- und einen von der 1. fork() ).

Nun wird das 2. fork() im Elternprozess ausgeführt, es tut es und es gibt einen Wert ungleich Null für den Elternprozess und eine Null Eins im Kindprozess zurück.

Nun wird der Elternteil die Ausführung bis zum letzten fork() (aufgrund von Kurzschlüssen) nicht fortsetzen, während der Kindprozess die letzte Verzweigung ausführen wird, da der erste Operand von || 0 ist.

Das bedeutet, dass wir zwei weitere Drucke bekommen werden.

Als Ergebnis erhalten wir insgesamt vier Drucke.

Kurzschluss

Hier bedeutet kurzschließen , dass wenn der erste Operand von & amp; & amp; ist Null, dann wird / werden der oder die anderen Operanden nicht ausgewertet. Auf der gleichen Logik, wenn ein Operand von einem || ist 1, dann brauchen die restlichen Operanden keine Auswertung. Dies geschieht, weil der Rest der Operanden das Ergebnis des logischen Ausdrucks nicht ändern kann, so dass sie nicht ausgeführt werden müssen, wodurch wir Zeit sparen.

Siehe Beispiel unten.

Prozess

Denken Sie daran, dass ein Elternprozess Nachkommenschaftsprozesse erzeugt, die wiederum andere Prozesse erzeugen und so weiter. Dies führt zu einer Hierarchie von Prozessen (oder einem Baum, könnte man sagen).

Wenn Sie das im Hinterkopf haben, sollten Sie sich dieses ähnliche Problem ansehen sowie diese Antwort.

Beschreibendes Bild

Ich habe auch diese Figur gemacht, die mir helfen kann. Ich nahm an, dass die% code_% der PID 3, 4 und 5 für jeden Anruf zurückgegeben werden.

Beachten Sie, dass einige fork() s ein rotes X über ihnen haben, was bedeutet, dass sie wegen der Kurzschlussauswertung des logischen Ausdrucks nicht ausgeführt werden.

Die fork() s am Anfang werden nicht ausgeführt, weil der erste Operand des Operators fork() 0 ist, daher ergibt der ganze Ausdruck 0, also keine Essenz beim Ausführen des restlichen Operanden (s) von && .

Das && am unteren Rand wird nicht ausgeführt, da es der zweite Operand eines fork() ist, wobei sein erster Operand eine von Null verschiedene Zahl ist, daher wird das Ergebnis des Ausdrucks bereits zu true, no ausgewertet Egal was der zweite Operand ist.

Und auf dem nächsten Bild sehen Sie die Hierarchie der Prozesse: basierend auf der vorherigen Abbildung.

Beispiel für Kurzzündung

%Vor%

Ausgabe:

%Vor%     
gsamaras 03.11.2014 14:33
quelle
13

Für alle Downvoter ist das eine vereinigte, aber andere Frage. Schuld SO. Danke.

Sie können das Problem in drei Zeilen zerlegen, wobei die erste und die letzte Zeile die Anzahl der Prozesse einfach verdoppeln.

%Vor%

Die Operatoren sind kurzgeschlossen, also erhalten Sie Folgendes:

%Vor%

Das sind also insgesamt 4 * 5 = 20 Prozesse, die jeweils eine Zeile drucken.

Hinweis: Wenn aus irgendeinem Grund fork () fehlschlägt (z. B. haben Sie ein Limit für die Anzahl der Prozesse), gibt es -1 zurück und Sie können dann andere Ergebnisse erhalten.

    
Karoly Horvath 17.08.2011 11:24
quelle
9

Ausführen von fork() && (fork() || fork()) , was passiert

Jedes fork gibt 2 Prozesse mit den Werten pid (parent) und 0 (child)

Erste Abzweigung:

  • Übergeordneter Rückgabewert ist pid not null = & gt; führt den && (fork() || fork()) aus
    • zweiter gabeler Elternwert ist pid not null stoppt die Ausführung von || part = & gt; drucken forked
    • zweiter Fork-Child-Wert = 0 = & gt; führt den || fork() aus
      • Drittes Fork Parent druckt forked
      • drittes fork-Kind druckt forked
  • child Rückgabewert ist 0 stoppe Ausführung der & Amp; & amp; Teil = & gt; druckt forked

Gesamt: 4 forked

    
Serge Ballesta 03.11.2014 14:49
quelle
8

Ich mag alle Antworten, die bereits eingereicht wurden. Wenn Sie Ihrer printf-Anweisung noch ein paar weitere Variablen hinzufügen würden, wäre es für Sie einfacher zu sehen, was passiert.

%Vor%

Auf meiner Maschine hat es diese Ausgabe erzeugt:

%Vor%     
Bradley Slavik 03.11.2014 22:18
quelle
5

Dieser Code:

%Vor%

bekommt 20 Prozesse für sich selbst und 20 mal wird Printf gehen.

Und für

%Vor%

printf wird insgesamt 5 mal gehen.

    
Mayank Dixit 01.12.2012 18:17
quelle