Redirecionar o descritor de arquivo d0 para ou de um arquivo envolve as seguintes etapas:
- Abra o arquivo. O arquivo é aberto em algum descritor de arquivos d1 .
- Duplique o descritor d0 para um descritor de arquivo não usado no momento que seja maior que d0 . Isso pode ser feito com o comando
F_DUPFD
da fcntl
chamada do sistema. Se d0 não estiver aberto, não faça nada para este passo.
- Duplicar d1 para d0 . Isso pode ser feito com
F_DUPFD
ou com dup2
.
- Fechar d1 .
O motivo pelo qual a duplicação aleatória é necessária é que os aplicativos não conseguem escolher o descritor de arquivo ao abrir o arquivo. As etapas 2 a 4 podem ser omitidas se d1 = d0 , mas o shell não pode garantir isso.
Quando o redirecionamento se aplica a um comando externo, ele é executado no processo filho, depois que o processo filho tiver sido criado com fork
mas antes de executar o comando externo com execve
. Quando o redirecionamento se aplica a um comando shell interno (por exemplo, uma chamada de função, um loop, etc.), essas etapas devem ser executadas no processo original¹ e o shell precisa restaurar o estado descritor de arquivo original após o comando redirecionado ser concluído. duplicando d2 de volta para d0 e fechando d2 (ou apenas fechando d0 se ele não estivesse inicialmente aberto) .
Um pipe envolve etapas semelhantes, mas é um pouco mais complicado porque a criação do canal cria dois descritores de arquivo (o final da leitura e o final da gravação) e há dois subprocessos.
-
Crie um canal com pipe
. A chamada do sistema pipe
retorna um par de descritores de arquivos { r , w }.
-
No lado esquerdo do tubo:
- Fechar r .
- Faça a duplicação aleatória para mover w para 1.
-
No lado direito do tubo:
- Fechar w .
- Faça a duplicação aleatória para mover r para 0.
-
Em shells que executam ambos os lados do pipe em subprocessos, o processo pai fecha r e w e aguarda que os dois lados do pipe terminem. / p>
Em shells que executam o lado direito do pipe no processo pai, o shell aguarda que o lado esquerdo termine, fecha 0 e restaura o descritor de arquivo original em 0.
Você pode ver o que os shells fazem lendo seu código-fonte ou seguindo-os em operação com um depurador. Por exemplo, no Linux, procure as chamadas do sistema em ação com
strace sh -c '…'
¹ As antigas shells (antes do POSIX) executavam comandos complexos redirecionados em um subprocesso, de modo que não precisavam de nenhuma restauração de redirecionamento.