4. Pipes “Anônimos” e Pipes Nomeados

Vamos voltar ao exemplo dos pipes, já que eles são bastante interessantes e também um bom exmplo das noções de links. Quando você usa um pipe em uma linha de comando, o shell cria o pipe para você e o coloca para funcionar, então o comando antes do pipe escreve nele e o comando depois do pipe lê a partir dele. Todos os pipes, quer sejam anônimos (como aqueles utilizados pelo shell) ou nomeados (veja abaixo) trabalha como FIFOs (First In, First Out - Primeiro que entra, primeiro que sai). Nós já vimos alguns exemplos de como usar pipes no shell, mas vamos dar outra olhada para o propósito de nossa demonstração:

$ ls -d /proc/[0-9] | head -5
/proc/1/
/proc/2/
/proc/3/
/proc/4/
/proc/5/

Uma coisa que você não vai perceber neste exemplo (porque ela acontece rápida demais para percebermos) é que a escrita em pipes é bloqueada. Isto significa que quando o comando ls escreve no pipe, ele fica bloqueado até que um processo na outra ponta leia o pipe. Para visualizar o efeito, você pode criar pipes nomeados, que ao contrário dos pipes utilizados pelo shell possuem nomes (ex.: eles são referenciados, enquanto os pipes do shell não são)[5]. O comando para criar um pipe nomeado é o mkfifo:

$ mkfifo a_pipe
$ ls -il
total 0
169 prw-rw-r--  1 usuario1 usuario1 0 Aug  6 19:37 a_pipe|
  #
  # Você pode ver que o contador de link é 1, e que a saída mostra
  # que  o arquivo é um pipe ('p').
  #
  # Você também pode usar o ln aqui:
  #
$ ln a_pipe the_same_pipe
$ ls -il
total 0
169 prw-rw-r--  2 usuario1 usuario1 0 Aug  6 19:37 a_pipe|
169 prw-rw-r--  2 usuario1 usuario1 0 Aug  6 19:37 the_same_pipe|
$ ls -d /proc/[0-9] >a_pipe
  #
  # O processo está bloqueado, já que não umprocesso para ler na 
  # outra ponta.
  # Digite Control Z para suspender o processo...
  #
[1]+  Stopped                 ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe
  #
  # ...Então coloque-o em background:
  #
$ bg
[1]+ ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe &
  #
  # agora leia-o a partir do pipe...
  #
$ head -5 <the_same_pipe
  #
  # ...o processo de escrita termina
  #
/proc/1/
/proc/2/
/proc/3/
/proc/4/
/proc/5/
[1]+  Done                    ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe
$

De maneira similar, leituras também estão bloqueadas. Se nós executarmos os comandos acima em ordem reversa, nós veremos que os blocos do head, esperando por algum processo para dar a ele algo para ler:

$ head -5 <a_pipe 
# 
# Blocos do programa, suspenso com: C-z 
# 
[1]+  Stopped                 head -5 <a_pipe 
# 
# Coloque-o no background...  
# 
$ bg 
[1]+ head -5 <a_pipe &
# 
# ...e alimente-o :) 
# 
$ ls -d /proc/[0-9] >the_same_pipe 
/proc/1/ 
/proc/2/ 
/proc/3/ 
/proc/4/ 
/proc/5/ 
[1]+  Done                    head -5 <a_pipe
$

Você também pode constatar um efeito não desejado no exemplo anterior: o comando ls terminou antes que o comando head o pegasse. A consequência disto é que você foi devolvido imediatamente para o prompt, mas o head foi executado depois e você só viu sua saída depois de retornar.



[5] Existem outras diferenças entre os dois tipos de pipes, mas estão fora do escopo deste livro.