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).
Nun, was genau ist die Ausgabe von :
? Was wird an den anderen weitergegeben :
?
':' 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.
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.
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 .
Ich denke, dass die gleiche Logik gilt für: () {: |: &} ;: und
:(){ : & };:
Macht den gleichen Job wie
:(){ :|: & };:
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.
:|:
diesem:
Fall muss der zweite Befehl nicht warten, bis der erste abgeschlossen ist.