Digamos que temos um pipe nomeado chamado fifo
, e estamos lendo e escrevendo nele de dois shells diferentes. Considere estes dois exemplos:
shell 1$ echo foo > fifo
<hangs>
shell 2$ cat fifo
foo
shell 1$ echo bar > fifo
<hangs>
shell 1$ cat > fifo
<typing> foo
<hangs>
shell 2$ cat fifo
foo
^C
shell 1$
<typing> bar
<exits>
Não consigo entender o que acontece nesses exemplos e, em particular, por que tentar escrever 'bar' no canal no primeiro exemplo resulta em uma chamada de bloqueio, enquanto no segundo exemplo aciona um SIGPIPE.
Entendo que, no primeiro caso, dois processos separados gravam no pipe e, portanto, ele é aberto duas vezes, enquanto no segundo caso é aberto apenas uma vez por um único processo e gravado duas vezes, com o processo lendo o pipe sendo morto nesse meio tempo. O que não entendo é como isso afeta o comportamento do write
.
A pipe(7)
página de manual afirma:
Se todos os descritores de arquivo referentes ao final de leitura de um pipe tiverem sido fechados, então uma gravação (2) fará com que um sinal SIGPIPE seja gerado para o processo de chamada.
Esta condição não parece clara para mim. Um descritor de arquivo fechado simplesmente deixa de ser um descritor de arquivo, certo? Como dizer " a extremidade de leitura do tubo foi fechada " difere de " a extremidade de leitura do tubo não está aberta "?
Espero que minha pergunta tenha sido clara o suficiente. A propósito, se você pudesse sugerir dicas para entender em detalhes o funcionamento dos pipes Unix em relação a open
, e operações close
, eu agradeceria muito.read
write
Seu exemplo está usando a
fifo
not apipe
, então está sujeito afifo(7)
.pipe(7)
também conta:Então agora de
fifo(7)
:Portanto, antes que ambas as extremidades (aqui significando que há pelo menos um leitor e um gravador) sejam abertas, escreva blocos de acordo com
fifo(7)
. Depois que ambas as extremidades foram abertas e, em seguida, (as) extremidades de leitura fechadas, a gravação gera SIGPIPE conformepipe(7)
.Para um exemplo de uso de pipe (não fifo), veja a seção de exemplo de
pipe(2)
: envolve pipe() (sem open(), já que pipe() realmente criou o par de pipes aberto), close(), read() write() e fork () (quase sempre há um fork () ao usar um pipe).A maneira mais simples de lidar com o SIGPIPE a partir do seu próprio código C, se você não quiser que ele morra ao gravar em um fifo, seria chamá
signal(SIGPIPE, SIG_IGN);
-lo e manipulá-lo verificando o errnoEPIPE
após cada gravação ().A gravação em um pipe ou FIFO que não possui um processo de leitura é tratada como uma condição de erro; ele gera um sinal SIGPIPE e falha com o código de erro EPIPE se o sinal for manipulado ou bloqueado.