Why does the server process have to open FIFO again, it just has to read again after a client process has written into it, right?
Interessante, vamos tentar sua sugestão. Os seguintes resultados foram gerados no Linux 4.9.0-6-amd64 (kernel do Ubuntu Linux).
$ mkfifo t
$ (cat; cat) < t & # run a "server" as a background job
[1] 4856
$ echo 1 > t
1
[1]+ Done ( cat; cat ) < t
Não funcionou como queríamos. O primeiro cat
lê EOF como esperado e, em seguida, sai. O problema é que o segundo cat
também lê EOF imediatamente, e assim nosso "servidor" termina. Não é possível esperar por um novo cliente (sem chamar repetidamente read () e desperdiçar tempo de CPU).
Se você souber como manipular descritores de arquivos (FDs) no shell, podemos ver isso de outra forma para ajudar a confirmar isso.
$ echo 1 > t &
$ exec 3 < t # open "t" for reading, as FD 3.
$ cat <&3
1
[1]+ Done echo 1 > t
$ cat <&3
$
$ echo 2 > t &
[1] 5102
$ cat <&3
2
[1]+ Done echo 2 > t
$ cat <&3
$
A resposta é que o que a recapitulação do fifo alcança, é impedir que alguém o abra para escrever. Sem essa etapa, todas as chamadas subsequentes para open()
do fifo retornarão imediatamente 0 (EOF).
Quando notei isso, imaginei como read()
funciona. Este programa emula o antigo systemd-initctl
fifo sob systemd. (Aviso: não é muito fácil testar isso; não vou me preocupar em documentar como). A resposta é que o systemd-initctl abre o fifo para leitura e escrita. (Tecnicamente é o systemd que abre o fifo, conforme especificado pelo systemd-initctl.socket, e passa para o systemd-initctl). Abrir um fifo para ler e escrever simultaneamente é um recurso específico do Linux. Mas ao fazer isso, o systemd está implementando o mesmo truque que Stevens menciona a seguir:
To avoid this, a useful technique is for the daemon to open the FIFO two times- once for reading and once for writing. The file descriptor returned for reading is used to read the client requests , and the file descriptor for writing is never used. By having the FIFO always open for writing (as long as the daemon process exists) the reads do not return an EOF, but wait for the next client request.