Aviso: A execução desse comando na maioria dos shells resultará em um sistema quebrado que precisará de um desligamento forçado para corrigir
Entendo a função recursiva :(){ :|: & };:
e o que ela faz. Mas eu não sei onde é a chamada do sistema fork. Não tenho certeza, mas suspeito no cano |
.
linux
shell
system-calls
mavillan
fonte
fonte
Respostas:
Como resultado da inserção do pipe
x | y
, um subshell é criado para conter o pipeline como parte do grupo de processos em primeiro plano. Isso continua a criar subshells (viafork()
) indefinidamente, criando assim uma bomba de forquilha.No entanto, a bifurcação não ocorre até que o código seja executado, que é a chamada final de
:
seu código.Para desmontar como a bomba dos garfos funciona:
:()
- defina uma nova função chamada:
{ :|: & }
- uma definição de função que canaliza recursivamente a função de chamada em outra instância da função de chamada em segundo plano:
- chame a função de bomba de garfoIsso tende a não consumir muita memória, mas absorve PIDs e consome ciclos da CPU.
fonte
x | y
, por que existe um sub-shell criado? Pelo que entendi, quando o bash vê umpipe
, ele executa apipe()
chamada do sistema, que retorna doisfds
. Agora, command_left éexec
ed e a saída é alimentada para command_right como entrada. Agora, command_right estáexec
ed. Então, por que éBASHPID
diferente a cada vez?x
ey
existem 2 comandos separados sendo executados em 2 processos separados, então você tem 2 subshells separados. Se forx
executado no mesmo processo que o shell, isso significa quex
deve ser incorporado.O último pedaço do código,
;:
está a executar a função:(){ ... }
. É aqui que o garfo está ocorrendo.O ponto-e-vírgula finaliza o primeiro comando e estamos iniciando outro, ou seja, invocando a função
:
. A definição dessa função inclui uma chamada para si mesma (:
) e a saída dessa chamada é canalizada para uma versão em segundo plano:
. Isso sustenta o processo indefinidamente.Toda vez que você está chamando a função
:()
que você está chamando a função Cfork()
. Eventualmente, isso esgotará todos os IDs de processo (PIDs) no sistema.Exemplo
Você pode trocar por
|:&
outra coisa para ter uma idéia do que está acontecendo.Configurar um inspetor
Em uma janela do terminal, faça o seguinte:
Configure a bomba do garfo com atraso de fusível
Em outra janela, rodaremos uma versão ligeiramente modificada da bomba de forquilha. Esta versão tentará se controlar para que possamos estudar o que está fazendo. Nossa versão irá dormir por 61 segundos antes de chamar a função
:()
.Também chamaremos a chamada inicial em segundo plano, depois que ela for chamada. Ctrl+ ze digite
bg
.Agora, se executarmos o
jobs
comando na janela inicial, veremos o seguinte:Após alguns minutos:
Verifique com o observador
Enquanto isso, na outra janela em que estamos executando
watch
:Hierarquia do processo
E a
ps -auxf
mostra essa hierarquia de processos:Tempo de limpeza
A
killall bash
irá parar as coisas antes que elas fiquem fora de controle. Fazer a limpeza dessa maneira pode ser um pouco pesado, uma maneira mais gentil e gentil, que nãobash
destrói todos os cascos, seria o seguinte:Determine em que pseudo terminal a bomba dos garfos será executada
Mate o pseudo terminal
Então o que está acontecendo?
Bem, cada invocação de
bash
esleep
é uma chamada para a função Cfork()
dobash
shell de onde o comando foi executado.fonte
bash
pode estar em execução em terminais separados. Melhor seria usarpkill -t pts/2
.