Você ou o livro está confundindo um subshell com um subprocesso que é um shell.
Algumas construções de shell fazem com que o shell bifurque o processo filho. No Linux, fork
é um caso especial da chamada de sistema clone
mais geral, que você observou no strace
log. O filho executa uma parte do script de shell. O processo filho é chamado de subshell . A construção mais direta é command1 &
: command1
é executada em um subshell e os comandos subseqüentes são executados no shell pai. Outras construções que criam uma subshell incluem a substituição de comando $(command2)
e pipes command3 | command4
( command3
é executado em uma subshell, command4
é executado em uma subshell na maioria das shells, mas não em ksh ou zsh).
Um subshell é uma cópia do processo pai, portanto, ele possui não apenas as mesmas variáveis de ambiente, mas também as mesmas definições internas: variáveis (incluindo $$
, o ID do processo original do shell), funções, aliases, opções, etc. Antes de executar o código no subshell, o bash define a variável BASHPID
como o ID do processo filho.
Quando você executa ./file
, isso executa um comando externo. Primeiro, o shell bifurca um processo filho; então este processo filho executa (com a chamada do sistema execve
) o arquivo executável ./file
. Um processo filho herda os atributos de processo de seus pais: ambiente, diretório atual, etc. Aspectos internos do aplicativo são perdidos na chamada execve
: variáveis não exportadas, funções, etc. são noções básicas que o kernel não sabe sobre, e eles são perdidos quando o bash executa outro programa. Mesmo que esse outro programa seja um script bash, ele é executado por uma nova instância do bash que não sabe ou não se importa que o processo pai também seja uma instância do bash. Assim, uma variável do shell (variável não exportada) não sobrevive a execve
.