Por que usar um pipe nomeado em vez de um arquivo?

42

Li recentemente sobre pipes nomeados e não conseguia entender por que eles existem.
Li em algum lugar que usar um pipe nomeado consome menos tempo do que usar um arquivo.

Porque isto é assim?
Os pipes nomeados também precisam ser armazenados na memória (e talvez trocados, assim como os arquivos).
Tanto quanto eu posso ver, eles devem obter um inode que deve ser referenciado pelo diretório atual, assim como arquivos. Além disso, eles devem ser removidos pelo programador, assim como os arquivos.

Então, onde está a vantagem?

user3122885
fonte
Isso não faz parte de um trabalho de sala de aula, é?
don.joey
6
não ... na verdade, eu estava olhando algumas anotações de aula quando encontrei essa pergunta e não consegui responder ... e se fosse uma tarefa, não vejo como isso seria relevante ... não é como Eu não iria procurar a resposta até que eu iria encontrá-lo
user3122885

Respostas:

41

Quase tudo no Linux pode ser considerado um arquivo , mas a principal diferença entre um arquivo comum e um pipe nomeado é que um pipe nomeado é uma instância especial de um arquivo que não possui conteúdo no sistema de arquivos.

Aqui está uma citação de man fifo:

Um arquivo especial FIFO (um pipe nomeado) é semelhante a um pipe, exceto pelo fato de ser acessado como parte do sistema de arquivos. Pode ser aberto por vários processos de leitura ou escrita. Quando os processos estão trocando dados via FIFO, o kernel passa todos os dados internamente sem gravá-los no sistema de arquivos. Portanto, o arquivo especial FIFO não possui conteúdo no sistema de arquivos; a entrada do sistema de arquivos serve apenas como um ponto de referência para que os processos possam acessar o canal usando um nome no sistema de arquivos.

O kernel mantém exatamente um objeto de pipe para cada arquivo especial FIFO que é aberto por pelo menos um processo. O FIFO deve ser aberto nas duas extremidades (leitura e gravação) antes que os dados possam ser transmitidos. Normalmente, abrir os blocos FIFO até que a outra extremidade também seja aberta.

Então, na verdade, um pipe nomeado não faz nada até que algum processo o leia e grave. Não ocupa espaço no disco rígido (exceto um pouco de meta informações), não usa a CPU.

Você pode verificá-lo fazendo o seguinte:

Crie um canal nomeado

$ mkfifo /tmp/testpipe

Vá para algum diretório, por exemplo /home/user/Documents, e gzip tudo dentro dele, usando pipe nomeado.

$ cd /home/user/Documents
$ tar cvf - . | gzip > /tmp/testpipe &
[1] 28584

Aqui você deve ver o PID do processo gzip. No nosso exemplo, era 28584.

Agora verifique o que este PID está fazendo

$ ps u -P 28584
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
c0rp     28584  0.0  0.0  29276  7800 pts/8    S    00:08   0:00 bash

Você verá que ele não está usando recursos . 0% de uso da CPU, 0% de uso de memória.

Verifique o palpite sobre o uso do espaço no arquivo

$ du -h /tmp/testpipe
0   testpipe

E novamente 0, nada. O tubo de teste pode ser usado novamente, se necessário.

Não esqueça de matar o gzip, usando kill -15 28584. E remova nosso pipe nomeado usandorm /tmp/testpipe

Exemplos de usos

Você pode redirecionar quase tudo usando o pipe nomeado. Como exemplo, você pode ver esse proxy de uma linha .

Também aqui está mais uma boa explicação do uso de pipes nomeados. Você pode configurar dois processos em um servidor para se comunicar usando um pipe nomeado em vez da pilha TCP / IP. É muito mais rápido e não carrega recursos de rede. Por exemplo, seu servidor Web pode se comunicar diretamente com o banco de dados usando um pipe nomeado, em vez de usar o localhostendereço ou escutar alguma porta.

c0rp
fonte
14

É verdade que você não usará a memória do sistema, mas o fato de não usar a CPU no seu exemplo é apenas porque você não lê o pipe, pelo que o processo está aguardando.

Considere o seguinte exemplo:

mkfifo /tmp/testpipe
tar cvf - / | gzip > /tmp/testpipe

Agora abra um novo console e execute:

watch -n 1 'ps u -P $(pidof tar)

E em um terceiro console:

cat /tmp/testpipe > /dev/null

Se você olhar para o relógio cmd (segundo período), ele mostrará um aumento no consumo de CPU!

GARCIN David
fonte
1
Esta resposta é sobre a resposta de
c0rp
2

Aqui está um caso de uso em que pipes nomeados podem economizar muito tempo removendo E / S.

Vamos supor que você tenha um BigFile, por exemplo, 10G.

Você também tem divisões deste BigFile em partes de 1G, BigFileSplit_01 a BigFile_Split_10.

Agora você tem uma dúvida sobre a correção do BigFileSplit_05

Ingenuamente, sem pipes nomeados, você criaria uma nova divisão do BigFile e compararia:

dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05

Com pipes nomeados, você faria

mkfifo BigFileSplitOrig_05
dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1 &
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05

Isso pode não parecer à primeira vista uma grande diferença ... mas com o tempo a diferença é enorme!

Opção 1:

  • dd: leia 1G / escreva 1G (1)
  • diff: leia 2G
  • rm: clusters alocados gratuitos / remover entrada do diretório

Opção 2:

  • dd: nada! (vai para o pipe nomeado)
  • diff: leia 2G
  • rm: nenhum cluster alocado para gerenciar (na verdade, não escrevemos nada no sistema de arquivos) / remover a entrada do diretório

Então, basicamente, o pipe nomeado poupa aqui uma leitura e gravação de 1G mais alguma limpeza do sistema de arquivos (uma vez que não escrevemos nada no sistema de arquivos, exceto o nó vazio).

Não fazer E / S, especialmente gravações, também é bom para evitar o desgaste de seus discos. É ainda mais interessante quando você trabalha com SSDs, pois eles têm um número limitado de gravações antes da morte das células.

(1) Obviamente, outra opção seria criar esse arquivo temporário na RAM, por exemplo, se / tmp estiver montado na RAM (tmpfs). No entanto, você ficaria limitado pelo tamanho do disco RAM, enquanto o "truque de tubulação nomeado" não tem limites.

Zakhar
fonte
1

Você pode deixar um programa parado e ouvir um pipe nomeado para algum evento externo. Assim que o evento externo ocorrer (por exemplo, chegada de alguns dados novos), isso poderá ser detectado por outro programa que, por sua vez, abre o canal para gravação, gravando os dados relevantes do evento no canal. Quando a instrução close é emitida, o programa de atendimento recebe o fluxo de dados através do canal por meio de uma instrução read e está pronto para processar o que obteve. Não se esqueça de fechar o tubo depois de ler o conteúdo. O programa de escuta também pode retornar resultados de seu processamento pelo mesmo ou por outro canal nomeado. Tais comunicações entre programas são muito convenientes às vezes.

Per Anton Ronning
fonte