A tubulação não exige que a primeira instância termine antes que a outra seja iniciada. Na verdade, tudo o que está realmente fazendo é redirecionar o stdout da primeira instância para o stdin do segundo, para que eles possam ser executados simultaneamente (como devem ser para o bomba de garfo para o trabalho).
Well, What exactly is the output of
:
? what is being passed to the other:
?
':' não está escrevendo nada para o outro ':' instância, está apenas redirecionando o stdout para o stdin da segunda instância. Se ele escreve alguma coisa durante sua execução (o que nunca acontecerá, já que ela não faz nada além de bifurcação), ela iria para o stdin da outra instância.
Isso ajuda a imaginar stdin e stdout como uma pilha:
O que estiver escrito no stdin será empilhado para quando o programa decidir ler, enquanto o stdout funciona da mesma maneira: uma pilha que você pode escrever para, assim outros programas podem ler quando quiserem.
Dessa forma, é fácil imaginar situações como um pipe que não tem nenhuma comunicação acontecendo (duas pilhas vazias) ou gravações e leituras não sincronizadas.
How exactly is that executed twice? In my opinion, nothing is passed to the second
:
until the first:
finishes its execution, which actually will never end.
Como estamos apenas redirecionando a entrada e a saída das instâncias, não há necessidade de a primeira instância terminar antes que a segunda seja iniciada. Na verdade, é geralmente desejável que ambos sejam executados simultaneamente, de modo que o segundo possa trabalhar com os dados sendo analisados pela primeira vez. Isso é o que acontece aqui, ambos serão chamados sem precisar esperar que o primeiro termine. Isso se aplica a todas as linhas de comandos pipe chains .
I am thinking that the same logic applies to :(){ :|: & };: and
:(){ : & };:
Does the same job as
:(){ :|: & };:
O primeiro não funcionaria, porque apesar de estar sendo executado recursivamente, a função está sendo chamada em segundo plano ( : &
). O primeiro :
não espera até que o "filho" :
retorne antes de terminar, então, no final, você provavelmente terá apenas uma instância de :
em execução. Se você tivesse :(){ : };:
, funcionaria, já que o primeiro :
aguardaria o retorno do "child" :
, o que esperaria que seu próprio "child" :
retornasse, e assim por diante. / p>
Veja como os comandos diferentes seriam exibidos em termos de quantas instâncias seriam executadas:
:(){ : & };:
1 instância (chama :
e sai) - > 1 instância (chama :
e sai) - > 1 instância (chama :
e sai) - > 1 instância - > ...
:(){ :|: &};:
1 instância (chama 2 :
e sai) - > 2 instâncias (cada um chama 2 :
e sai) - > 4 instâncias (cada um chama 2 :
e sai) - > 8 instâncias - > ...
:(){ : };:
1 instância (chama :
e aguarda a devolução) - > 2 instâncias (filho chama outro :
e aguarda a sua devolução) - > 3 instâncias (filho chama outro :
e aguarda que ele volte) - > 4 instâncias - > ...
:(){ :|: };:
1 instância (chama 2 :
's e espera que retornem) - > 3 instâncias (as crianças chamam 2 :
cada e esperam que voltem) - > 7 instâncias (as crianças chamam 2 :
cada e esperam que voltem) - > 15 instâncias - > ...
Como você pode ver, chamar a função em segundo plano (usando &
) retarda a bomba do fork, porque o chamado será encerrado antes que as funções chamadas retornem.