Duas janelas, mesmo usuário, com prompts do bash. Na janela 1, digite:
$ mkfifo f; exec <f
Portanto, o bash agora está tentando ler o descritor de arquivo 0, que é mapeado para o pipe nomeado f
. Na janela 2, digite:
$ echo ls > f
Agora a janela 1 imprime um sl e o shell morre. Por quê?
Próxima experiência: abra a janela-1 novamente com exec <f
. Na janela 2, digite:
$ exec 3>f
$ echo ls >&3
Após a primeira linha acima, a janela 1 é ativada e imprime um prompt. Por quê? Após a segunda linha acima, a janela 1 imprime a ls
saída 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 ?!
file-descriptors
fifo
Fixee
fonte
fonte
exec <f
,bash
não está tentando ler a partirf
, é primeira tentativa de abrir -lo. Eleopen()
não retornará até que haja algum processo fazendo outra abertura no modo de gravação no canal (nesse momento, o canal será instanciado e o shell lerá a entrada dele).exec 3>f
executado, o primeiro shell fornece um prompt. (PontoRespostas:
Tem a ver com o fechamento do descritor de arquivo.
No seu primeiro exemplo,
echo
grava em seu fluxo de saída padrão com o qual o shell é aberto para conectá-lo ef
, quando termina, seu descritor é fechado (pelo shell). No lado de recebimento, o shell, que lê a entrada de seu fluxo de entrada padrão (conectado af
) lêls
, é executadols
e finalizado devido à condição de fim de arquivo em sua entrada padrão.A condição de fim de arquivo ocorre porque todos os gravadores no pipe nomeado (apenas um neste exemplo) fecharam sua extremidade do pipe.
No seu segundo exemplo,
exec 3>f
abre o descritor de arquivo 3 para gravarf
e depoisecho
gravals
nele. É o shell que agora tem o descritor de arquivo aberto, não oecho
comando. O descritor permanece aberto até vocêexec 3>&-
. No lado de recebimento, o shell, que lê a entrada de seu fluxo de entrada padrão (conectado af
) lêls
, executals
e aguarda por mais entrada (já que o fluxo ainda está aberto).O fluxo permanece aberto porque todos os gravadores (o shell, via
exec 3>f
eecho
) não fecharam a extremidade do tubo (exec 3>f
ainda está em vigor).Eu escrevi sobre
echo
acima como se fosse um comando externo. Provavelmente está embutido no shell. O efeito é o mesmo, no entanto.fonte
Não há muito o que fazer: quando não há gravadores no canal, ele parece fechado para os leitores, ou seja, retorna EOF quando lido e bloqueia quando aberto.
Na página do manual do Linux (
pipe(7)
, mas veja tambémfifo(7)
):Fechar o final da gravação é o que acontece implicitamente no final do
echo ls >f
e, como você diz, no outro caso, o descritor de arquivo é mantido aberto.fonte
Depois de ler as duas respostas de @Kusalananda e @ikkachu, acho que entendi. Na janela 1, o shell está aguardando algo abrir a extremidade de gravação do pipe e depois fechá-la. Depois que o final da gravação é aberto, o shell na janela-1 imprime um prompt. Depois que o final da gravação é fechado, o shell obtém EOF e morre.
Do lado da janela-2 temos as duas situações descritas na minha pergunta: na primeira situação com
echo ls > f
, não há nenhum descritor de arquivo 3, por isso temosecho
de desova, e suastdin
estdout
olhar como este:Em seguida,
echo
termina e o shell fecha os dois descritores. Como o descritor de arquivo 1 está fechado e faz referênciaf
, o final da gravação def
é fechado e isso faz com que um EOF seja exibido na janela 1.Na segunda situação, executamos
exec 3>f
em nosso shell, fazendo com que o shell pegue este ambiente:Agora, rodamos
echo ls >& 3
e o shell aloca descritores de arquivos daecho
seguinte maneira:Em seguida, o shell fecha os três descritores acima, incluindo
f
, masf
ainda tem uma referência a partir do próprio shell. Essa é a diferença importante. Fechar o descritor 3exec 3>&-
fecharia a última referência aberta e causaria um EOF na janela 1, como observou @Kusalananda.fonte