L'ultimo bit del codice ;:
sta eseguendo la funzione :(){ ... }
. Questo è dove si sta verificando il fork.
Il punto e virgola termina il primo comando e ne stiamo iniziando un altro, ovvero invocando la funzione :
. La definizione di questa funzione include una chiamata a se stessa ( :
) e l'output di questa chiamata viene reindirizzato a una versione in background :
. Questo sostiene il processo indefinitamente.
Ogni volta che si sta chiamando la funzione :()
che si sta chiamando la funzione C fork()
. Alla fine ciò esaurirà tutti gli ID di processo (PID) sul sistema.
Esempio
Puoi scambiarlo |:&
con qualcos'altro in modo da avere un'idea di cosa sta succedendo.
Installa un osservatore
In una finestra del terminale, procedere come segue:
$ watch "ps -eaf|grep \"[s]leep 61\""
Installare la bomba a forcella "ritardato miccia"
In un'altra finestra eseguiremo una versione leggermente modificata della bomba a forcella. Questa versione tenterà di limitare se stessa in modo da poter studiare cosa sta facendo. La nostra versione dormirà per 61 secondi prima di chiamare la funzione :()
.
Inoltre eseguiremo anche la chiamata iniziale, dopo che è stata invocata. Ctrl+ z, quindi digitare bg
.
$ :(){ sleep 61; : | : & };:
# control + z
[1]+ Stopped sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &
Ora se eseguiamo il jobs
comando nella finestra iniziale vedremo questo:
$ jobs
[1]- Running sleep 61 &
[2]+ Running : | : &
Dopo un paio di minuti:
$ jobs
[1]- Done sleep 61
[2]+ Done : | :
Verifica con l'osservatore
Nel frattempo nell'altra finestra dove stiamo correndo watch
:
Every 2.0s: ps -eaf|grep "[s]leep 61" Sat Aug 31 12:48:14 2013
saml 6112 6108 0 12:47 pts/2 00:00:00 sleep 61
saml 6115 6110 0 12:47 pts/2 00:00:00 sleep 61
saml 6116 6111 0 12:47 pts/2 00:00:00 sleep 61
saml 6117 6109 0 12:47 pts/2 00:00:00 sleep 61
saml 6119 6114 0 12:47 pts/2 00:00:00 sleep 61
saml 6120 6113 0 12:47 pts/2 00:00:00 sleep 61
saml 6122 6118 0 12:47 pts/2 00:00:00 sleep 61
saml 6123 6121 0 12:47 pts/2 00:00:00 sleep 61
Gerarchia di processo
E a ps -auxf
mostra questa gerarchia di processi:
$ ps -auxf
saml 6245 0.0 0.0 115184 5316 pts/2 S 12:48 0:00 bash
saml 6247 0.0 0.0 100988 468 pts/2 S 12:48 0:00 \_ sleep 61
....
....
saml 6250 0.0 0.0 115184 5328 pts/2 S 12:48 0:00 bash
saml 6268 0.0 0.0 100988 468 pts/2 S 12:48 0:00 \_ sleep 61
saml 6251 0.0 0.0 115184 5320 pts/2 S 12:48 0:00 bash
saml 6272 0.0 0.0 100988 468 pts/2 S 12:48 0:00 \_ sleep 61
saml 6252 0.0 0.0 115184 5324 pts/2 S 12:48 0:00 bash
saml 6269 0.0 0.0 100988 464 pts/2 S 12:48 0:00 \_ sleep 61
...
...
Tempo di pulizia
A killall bash
fermerà le cose prima che sfuggano di mano. Fare la tua pulizia in questo modo può essere un po 'pesante, un modo più gentile e gentile che potenzialmente non strapperà ogni bash
guscio, sarebbe fare quanto segue:
Determina in quale pseudo terminale verrà lanciata la bomba
$ tty
/dev/pts/4
Uccidi lo pseudo terminale
$ pkill -t pts/4
Quindi cosa sta succedendo?
Bene, ogni invocazione di bash
ed sleep
è una chiamata alla funzione C fork()
dalla bash
shell da cui è stato eseguito il comando.