Nachdem ich die berühmten Fork Bomb-Fragen auf Askubuntu und vielen anderen Stack Exchange-Sites durchgesehen habe, verstehe ich nicht ganz, was alle sagen, als ob es offensichtlich wäre.
Viele Antworten ( Bestes Beispiel ) sagen dies:
"
{:|: &}
bedeutet, die Funktion auszuführen:
und ihre Ausgabe erneut an die:
Funktion zu senden "
Nun, was genau ist die Ausgabe von :
? Was wird an den anderen weitergegeben :
?
Und auch:
Im Wesentlichen erstellen Sie eine Funktion, die sich bei jedem Aufruf zweimal selbst aufruft und keine Möglichkeit hat, sich selbst zu beenden.
Wie genau wird das zweimal ausgeführt ? Meiner Meinung nach wird nichts an den zweiten weitergegeben, :
bis der erste :
seine Ausführung beendet hat, was eigentlich niemals enden wird.
In C
zum Beispiel
foo()
{
foo();
foo(); // never executed
}
die zweite foo()
wird überhaupt nicht ausgeführt, nur weil die erste foo()
niemals endet.
Ich denke, dass die gleiche Logik für :(){ :|: & };:
und gilt
:(){ : & };:
macht den gleichen Job wie
:(){ :|: & };:
Bitte helfen Sie mir, die Logik zu verstehen.
quelle
:|:
diesem:
Fall muss der zweite Befehl nicht warten, bis der erste abgeschlossen ist.Antworten:
Das Piping erfordert nicht, dass die erste Instanz beendet wird, bevor die andere gestartet wird. Eigentlich ist alles, was es wirklich tut, die Standardausgabe der ersten Instanz auf die Standardausgabe der zweiten Instanz umzuleiten , damit sie gleichzeitig ausgeführt werden können (da dies erforderlich ist, damit die Gabelbombe funktioniert).
':' schreibt nichts in die andere ':' Instanz, sondern leitet nur die stdout zur stdin der zweiten Instanz um. Wenn es während seiner Ausführung etwas schreibt (was es niemals tut, da es nichts anderes tut als sich selbst zu forken), würde es zum Standard der anderen Instanz gehen.
Es hilft, sich stdin und stdout als Stapel vorzustellen :
Was auch immer in das stdin geschrieben wird, wird bereit gestapelt, wenn das Programm entscheidet, davon zu lesen, während das stdout auf die gleiche Weise funktioniert: Ein Stapel, auf den Sie schreiben können, damit andere Programme es lesen können, wenn sie wollen.
Auf diese Weise können Sie sich Situationen wie eine Pipe ohne Kommunikation (zwei leere Stapel) oder nicht synchronisierte Schreib- und Lesevorgänge vorstellen.
Da wir nur die Ein- und Ausgabe der Instanzen umleiten, muss die erste Instanz nicht beendet werden, bevor die zweite gestartet wird. Eigentlich ist es normalerweise erwünscht, dass beide gleichzeitig ausgeführt werden, damit die zweite sofort mit den Daten arbeiten kann, die von der ersten analysiert werden. Das ist, was hier passiert, beide werden angerufen, ohne warten zu müssen, bis der erste fertig ist. Dies gilt für alle Befehlszeilen von Pipe Chains .
Das erste würde nicht funktionieren, da die Funktion im Hintergrund (
: &
) aufgerufen wird, obwohl sie selbst rekursiv ausgeführt wird . Das erste:
wartet nicht, bis das "Kind":
zurückkehrt, bevor es sich selbst beendet. Am Ende hätten Sie wahrscheinlich nur eine Instanz:
ausgeführt. Wenn Sie:(){ : };:
es hätten, würde es funktionieren, da das erste:
auf die:
Rückkehr des "Kindes" warten würde, das auf die Rückkehr des eigenen "Kindes" warten würde:
, und so weiter.So würden verschiedene Befehle in Bezug auf die Anzahl der ausgeführten Instanzen aussehen:
:(){ : & };:
1 Instanz (ruft auf
:
und beendet sich) -> 1 Instanz (ruft auf:
und beendet sich) -> 1 Instanz (ruft auf:
und beendet sich) -> 1 Instanz -> ...:(){ :|: &};:
1 Instanz (ruft 2 auf
:
und beendet) -> 2 Instanzen (jeder ruft 2:
auf und beendet) -> 4 Instanzen (jeder ruft 2:
auf und beendet) -> 8 Instanzen -> ...:(){ : };:
1 Instanz (ruft auf
:
und wartet auf Rückkehr) -> 2 Instanzen (Kind ruft eine andere auf:
und wartet auf Rückkehr) -> 3 Instanzen (Kind ruft eine andere auf:
und wartet auf Rückkehr) -> 4 Instanzen -> ...:(){ :|: };:
1 Instanz (ruft 2 auf
:
und wartet auf ihre Rückkehr) -> 3 Instanzen (Kinder rufen jeweils 2 auf:
und warten auf ihre Rückkehr) -> 7 Instanzen (Kinder rufen jeweils 2 auf:
und warten auf ihre Rückkehr) -> 15 Instanzen -> ...Wie Sie sehen,
&
verlangsamt das Aufrufen der Funktion im Hintergrund (mithilfe von ) die Abzweigbombe, da der Angerufene beendet wird, bevor die aufgerufenen Funktionen zurückkehren.quelle
:(){ : & && : &}; :
auch als Gabelbombe funktionieren? Sie würden auch exponentiell zunehmen, und tatsächlich könnten Sie mehrere einsetzen: &
, um es noch schneller zu erhöhen.bash: syntax error near unexpected token &&'
. Sie könnten dies tun::(){ $(: &) && $(: &)}; :
Aber im Gegensatz zur Pipeline wird das nicht parallel laufen. Welches wäre gleichbedeutend mit:(){: & };:
. Möchten Sie überprüfen? versuchen Sie diestime $( $(sleep 1 & ) && $(sleep 1 &) )
und dastime $(sleep 1 | sleep 1)
:(){ $(: &) && $(: &)};
ist eine Funktion, die eine logische AND-Operation in den Rückgabewerten der ersten und zweiten Instanz ausgibt. Das Problem ist, dass aus Effizienzgründen nur die erste Instanz ausgeführt wird, da ein logisches UND nur dann zutrifft, wenn beide Werte zutrifft. Wenn sein Rückgabewert 1 ist, wird die zweite Instanz ausgeführt. Wenn du die:(){ :|:|: &}; :
if [ prog1 ]; then; prog2; fi
)prog1 && prog2
auszuführen, können Sie auch nur write ( ) ausführen, und prog2 wird nur ausgeführt, wenn der Rückgabewert von prog1 wahr ist.&&
angerufenapt-get update && apt-get upgrade
und&
am Ende der Leitung im Hintergrund ausgeführt, aber das ist ein großartiger Punkt, dass sie nicht zusammenarbeiten. Ein Semikolon funktioniert auch nicht mit dem kaufmännischen Und.