Dado
cmd='fun(){ echo "$@"; }; fun $(fun $(fun hi))'
conchas tendem a precisar fazer 2 garfos para que isso aconteça
strace-f(){ strace -f "$@" 2>&1; };
for sh in dash bash zsh ksh; do
printf "$sh\t" ; strace-f $sh -c "$cmd" |grep -e clone -e fork -c;
done
exceto ksh
heroicamente faz isso sem bifurcar uma vez:
dash 2
bash 2
zsh 2
ksh 0
Como isso acontece?
Editar:
Aqui está como ele desce com um cano lançado:
cmd='fun(){ echo "$@"| echo "$@"; }; fun $(fun $(fun hi))'
Resultado:
dash 11
bash 10
zsh 5
ksh 3
shell
ksh
command-substitution
fork
optimization
PSkocik
fonte
fonte
ksh
instalou? Quando executo seu código, obtenho0
qualquer shell que não tenha instaladoRespostas:
O Ksh93 faz muito para evitar garfos. Não tenho idéia de como ele sabe lidar com o primeiro caso, pois
truss
mostra que ele chama apenas umawrite(2)
chamada com o resultado final.Pode ser que David varra o comando em macro.c e saiba que ele pode lidar com "eco" internamente.
O que posso dizer é que reescrevi o analisador e o intérprete do "Bourne Shell" no ano passado e reduzi principalmente o número de garfos e substitui muitos deles por
vfork()
chamadas. Atualmente, isso faz do Bourne Shell o segundo shell mais rápido que passou pelo ksh93. Você também pode executar seus testesbosh
.Entre: ksh93 evita garfos em geral. Ele implementa uma estrutura que contém todas as variáveis globais anteriores e isso tornou o código do shell reentrante, se for chamado com instâncias diferentes do ponteiro de estrutura de variável "global".
Este método é usado pelo ksh93 sempre que houver um
(cmd)
subshell.A razão para essa reescrita é que David está usando o Win-DOS em seu laptop e ele não gostou do lento Cygwin; portanto, ele escreveu UWIN e usa o ksh93 diretamente no Win-DOS. Como não existe
fork()
no Win-DOS, ele precisava encontrar uma nova solução ...fonte