pipes nomeados, descritores de arquivos e EOF

10

Duas janelas, mesmo usuário, com prompts bash. No tipo de janela 1:

$ mkfifo f; exec <f

Então o bash agora está tentando ler o descritor de arquivo 0, que é mapeado para o named pipe f . No tipo de janela 2:

$ echo ls > f

Agora o window-1 imprime um ls e depois o shell morre. Por quê?

Próximo experimento: abra a janela-1 novamente com exec <f . No tipo de janela 2:

$ exec 3>f
$ echo ls >&3

Após a primeira linha acima, o window-1 é ativado e imprime um prompt. Por quê? Após a segunda linha acima, a janela 1 imprime a saída ls e o shell permanece ativo. Por quê? De fato, agora na janela 2, echo ls > f não fecha o shell da janela 1.

A resposta deve ter a ver com a existência do descritor de arquivo 3 da janela-2 referenciando o pipe nomeado?!

    
por Fixee 19.06.2018 / 21:46

3 respostas

11

Tem a ver com o fechamento do descritor de arquivos.

No seu primeiro exemplo, echo grava em seu fluxo de saída padrão que o shell abre para conectá-lo com f e, quando ele termina, seu descritor é fechado (pelo shell). Na extremidade de recebimento, o shell, que lê a entrada de seu fluxo de entrada padrão (conectado a f ) lê ls , executa ls e, em seguida, termina devido à condição de fim de arquivo em sua entrada padrão. / p>

A condição de final de arquivo ocorre porque todos os escritores do canal nomeado (apenas um neste exemplo) fecharam o final do canal.

Em seu segundo exemplo, exec 3>f abre o descritor de arquivos 3 para gravar em f e, em seguida, echo escreve ls . É o shell que agora tem o descritor de arquivo aberto, não o comando echo . O descritor permanece aberto até você fazer exec 3>&- . Na extremidade de recepção, o shell, que lê a entrada de seu fluxo de entrada padrão (conectado a f ), lê ls , executa ls e aguarda por mais entrada (já que o fluxo ainda está aberto).

O fluxo permanece aberto porque todos os autores (shell, via exec 3>f e echo ) não fecharam o final do canal ( exec 3>f ainda está em vigor) .

Eu escrevi sobre echo acima como se fosse um comando externo. É mais provável que seja construído no shell. O efeito é o mesmo, no entanto.

    
por 19.06.2018 / 21:53
6

Não há muito: quando não há gravadores para o pipe, ele parece fechado para os leitores, ou seja, retorna EOF quando lido e bloqueia quando aberto.

Na página man do Linux ( pipe(7) , veja também fifo(7) ):

If all file descriptors referring to the write end of a pipe have been closed, then an attempt to read(2) from the pipe will see end- of-file (read(2) will return 0).

Fechar o final da gravação é o que implicitamente acontece no final do echo ls >f e, como você diz, no outro caso, o descritor do arquivo é mantido aberto.

    
por 19.06.2018 / 21:55
2

Depois de ler as duas respostas de @Kusalananda e @ikkachu, acho que entendi. Na janela 1, o shell está aguardando algo para abrir a extremidade de gravação do tubo e, em seguida, fechá-lo. Quando a extremidade de gravação é aberta, o shell na janela-1 imprime um prompt. Uma vez que o final da gravação é fechado, o shell obtém EOF e morre.

No lado da janela-2, temos as duas situações descritas na minha pergunta: na primeira situação com echo ls > f , não há descritor de arquivo 3, então temos echo spawning e seu stdin e stdout tem esta aparência:

0 --> tty
1 --> f

Então echo termina e o shell fecha ambos os descritores. Como o descritor de arquivo 1 é fechado e faz referência a f , o final de gravação de f é fechado e isso causa um EOF para a janela-1.

Na segunda situação, executamos exec 3>f em nosso shell, fazendo com que o shell execute esse ambiente:

bash:
0 --> tty
1 --> tty
2 --> tty
3 --> f

Agora, executamos echo ls >& 3 e o shell aloca os descritores de arquivo para echo da seguinte forma:

echo:
0 --> tty
1 --> f     # because 3 points to f
2 --> tty

Em seguida, o shell fecha os três descritores acima, incluindo f , mas f tem uma referência a ele do próprio shell. Essa é a diferença importante. O descritor de fechamento 3 com exec 3>&- fecharia a última referência aberta e causaria um EOF para a janela-1, como anotado @Kusalananda.

    
por 19.06.2018 / 22:24