Warnung: Das Ausführen dieses Befehls in den meisten Shells führt zu einem Systemausfall, für dessen Behebung ein erzwungenes Herunterfahren erforderlich ist
Ich verstehe die rekursive Funktion :(){ :|: & };:
und was sie tut. Aber ich weiß nicht, wo der Anruf beim Gabelsystem ist. Ich bin mir nicht sicher, aber ich vermute in der Pfeife |
.
linux
shell
system-calls
Mavillan
quelle
quelle
Antworten:
Als Ergebnis der
x | y
eingehenden Pipe wird eine Subshell erstellt, die die Pipeline als Teil der Vordergrundprozessgruppe enthält. Dies setzt fort, Unterschalen (überfork()
) auf unbestimmte Zeit zu erzeugen , wodurch eine Gabelbombe erzeugt wird.Die Verzweigung tritt jedoch erst auf, wenn der Code ausgeführt wird. Dies ist der letzte Aufruf
:
in Ihrem Code.So zerlegen Sie die Funktionsweise der Gabelbombe:
:()
- eine neue Funktion definieren, die aufgerufen wird:
{ :|: & }
- Eine Funktionsdefinition, die die aufrufende Funktion rekursiv in eine andere Instanz der aufrufenden Funktion im Hintergrund leitet:
- Gabelbombenfunktion aufrufenDies ist in der Regel nicht zu speicherintensiv, saugt jedoch PIDs auf und verbraucht CPU-Zyklen.
quelle
x | y
, warum gibt es eine Unterschale geschaffen? Wenn bash a siehtpipe
, führt es meines Erachtens einenpipe()
Systemaufruf aus, der zwei zurückgibtfds
. Jetzt wird command_left editiertexec
und die Ausgabe als Eingabe an command_right übergeben. Jetzt ist command_right editiertexec
. Also, warum istBASHPID
jedes Mal anders?x
und esy
gibt 2 separate Befehle, die in 2 separaten Prozessen ausgeführt werden, sodass Sie 2 separate Subshells haben. Wennx
im selben Prozess wie die Shell ausgeführt wird,x
muss dies eine integrierte sein.Das letzte Bit des Codes
;:
führt die Funktion aus:(){ ... }
. Hier tritt die Gabel auf.Das Semikolon beendet den ersten Befehl und wir starten einen anderen, dh wir rufen die Funktion auf
:
. Die Definition dieser Funktion beinhaltet einen Aufruf an sich selbst (:
) und die Ausgabe dieses Aufrufs wird an eine Hintergrundversion weitergeleitet:
. Dies beschleunigt den Prozess auf unbestimmte Zeit.Jedes Mal, wenn Sie die Funktion
:()
aufrufen, rufen Sie die C-Funktion auffork()
. Letztendlich werden dadurch alle Prozess-IDs (PIDs) im System erschöpft.Beispiel
Sie können das
|:&
mit etwas anderem austauschen, um eine Vorstellung davon zu bekommen, was los ist.Richten Sie einen Beobachter ein
Führen Sie in einem Terminalfenster Folgendes aus:
Richten Sie die Gabelbombe "Sicherung verzögert" ein
In einem anderen Fenster führen wir eine leicht modifizierte Version der Gabelbombe aus. Diese Version wird versuchen, sich selbst zu drosseln, damit wir untersuchen können, was es tut. Unsere Version wartet 61 Sekunden, bevor sie die Funktion aufruft
:()
.Außerdem wird der erste Aufruf nach dem Aufrufen ebenfalls im Hintergrund ausgeführt. Ctrl+ z, dann tippe
bg
.Wenn wir nun den
jobs
Befehl im Anfangsfenster ausführen, sehen wir Folgendes:Nach ein paar Minuten:
Checken Sie mit dem Beobachter ein
In der Zwischenzeit in dem anderen Fenster, in dem wir laufen
watch
:Prozesshierarchie
Und a
ps -auxf
zeigt diese Prozesshierarchie:Putzzeit
A
killall bash
stoppt die Dinge, bevor sie außer Kontrolle geraten. Wenn Sie auf diese Weise bereinigen, ist dies möglicherweise etwas umständlich. Dies ist eine schonendere Methode, die möglicherweise nicht allebash
Muscheln abreißt.Bestimmen Sie, in welchem Pseudoterminal die Gabelbombe laufen wird
Töte das Pseudoterminal
So was ist los?
Nun, jeder Aufruf von
bash
undsleep
ist ein Aufruf der C-Funktionfork()
von derbash
Shell aus, von der aus der Befehl ausgeführt wurde.quelle
bash
wird möglicherweise auf separaten Terminals ausgeführt. Besser wäre es zu benutzenpkill -t pts/2
.