Avertissement: l'exécution de cette commande dans la plupart des shells entraînera un système défectueux qui nécessitera un arrêt forcé pour être corrigé
Je comprends la fonction récursive :(){ :|: & };:
et ce qu'elle fait. Mais je ne sais pas où est l'appel système fork. Je ne suis pas sûr, mais je soupçonne dans la pipe |
.
linux
shell
system-calls
mavillan
la source
la source
Réponses:
À la suite de l'entrée du tuyau
x | y
, un sous-shell est créé pour contenir le pipeline en tant que partie du groupe de processus de premier plan. Cela continue de créer des sous-coquilles (viafork()
) indéfiniment, créant ainsi une bombe fourchette.Cependant, le fork ne se produit pas tant que le code n'est pas exécuté, ce qui est l'invocation finale de
:
dans votre code.Pour démonter le fonctionnement de la bombe à fourche:
:()
- définir une nouvelle fonction appelée:
{ :|: & }
- une définition de fonction qui redirige récursivement la fonction appelante dans une autre instance de la fonction appelante en arrière-plan:
- appelez la fonction de bombe à fourcheCela a tendance à ne pas être trop gourmand en mémoire, mais il aspire les PID et consomme des cycles CPU.
la source
x | y
, pourquoi y a-t-il un sous-shell créé? Pour ma compréhension, quand bash voit unpipe
, il exécutepipe()
un appel système, qui renvoie deuxfds
. Maintenant, command_left estexec
édité et la sortie est envoyée à command_right en entrée. Maintenant, command_right estexec
édité. Alors, pourquoi est-ceBASHPID
différent à chaque fois?x
et ily
y a 2 commandes distinctes exécutées dans 2 processus distincts, vous avez donc 2 sous-coquilles distinctes. Six
s'exécute dans le même processus que le shell, cela signifie qu'ilx
doit être intégré.Le dernier bit du code,
;:
exécute la fonction:(){ ... }
. C'est là que la fourche se produit.Le point-virgule termine la première commande, et nous en commençons une autre, c'est-à-dire en invoquant la fonction
:
. La définition de cette fonction inclut un appel à lui-même (:
) et la sortie de cet appel est dirigée vers une version en arrière-plan:
. Cela soutient indéfiniment le processus.Chaque fois que vous appelez la fonction
:()
que vous appelez la fonction Cfork()
. Finalement, cela épuisera tous les ID de processus (PID) sur le système.Exemple
Vous pouvez échanger le
|:&
avec quelque chose d'autre pour vous faire une idée de ce qui se passe.Configurer un observateur
Dans une fenêtre de terminal, procédez comme suit:
Configuration de la bombe à fourche "fusible retardé"
Dans une autre fenêtre, nous exécuterons une version légèrement modifiée de la bombe à fourche. Cette version tentera de se limiter afin que nous puissions étudier ce qu'elle fait. Notre version dormira pendant 61 secondes avant d'appeler la fonction
:()
.Nous allons également mettre en arrière-plan l'appel initial, après son appel. Ctrl+ z, puis tapez
bg
.Maintenant, si nous exécutons la
jobs
commande dans la fenêtre initiale, nous verrons ceci:Après quelques minutes:
Vérifiez auprès de l'observateur
Pendant ce temps, dans l'autre fenêtre où nous courons
watch
:Hiérarchie des processus
Et un
ps -auxf
montre cette hiérarchie de processus:Temps de nettoyage
A
killall bash
arrêtera les choses avant qu'elles ne deviennent incontrôlables. Faire votre nettoyage de cette façon peut être un peu dur, une manière plus douce et plus douce qui ne détruira pas potentiellement chaquebash
coquille, serait de faire ce qui suit:Déterminez dans quel pseudo terminal la bombe à fourche va s'exécuter
Tuez le pseudo terminal
Alors que se passe-t-il?
Eh bien, chaque appel de
bash
etsleep
est un appel à la fonction C àfork()
partir dubash
shell à partir duquel la commande a été exécutée.la source
bash
peut être exécuté sur des terminaux distincts. Mieux serait d'utiliserpkill -t pts/2
.