7.6.2 Le pipe

Un comando può essere rediretto40 utilizzando le pipe41, specificando sulla riga di comando il carattere ‘|’ (detto appunto pipe). Così facendo l’output del comando che precede il simbolo ‘|’ viene rediretto nell’input del comando che lo segue, per mezzo di una pipe (una sorta di tubo). Ad esempio, nella riga di comando seguente

 
$ ls | pr | lpr  
l’output del comando ls, cioè l’elenco dei file contenuti nella working directory, viene rediretto nell’input del comando pr che si occupa di suddividerlo in pagine. Quindi, l’output del comando pr viene rediretto nell’input del comando lpr che provvede ad inviare la stampa alla stampante di default. I singoli processi non si accorgono della redirezione del loro input/output, ed eseguono tutto come se non fosse richiesta alcuna redirezione. È la shell che si occupa di gestire la redirezione, creando le opportune pipe.

In GNU/Linux, una pipe è implementata utilizzando, per ogni processo, due strutture file (file descriptor) che puntano entrambe allo stessa zona di memoria (buffer) del kernel. In particolare uno dei due file descriptor accede al buffer del kernel (pipe) in lettura e l’altro in scrittura. Quando viene generato un processo figlio, questo condivide i file descriptor del padre, quindi se uno dei due processi scrive su una pipe, l’altro può leggervi. Il kernel deve comunque garantire che vi sia una sincronizzazione tra le operazioni di lettura e scrittura su di una pipe e lo fa utilizzando meccanismi di lock, code di attesa e segnali.

Un processo accede in lettura e scrittura ad una pipe per mezzo delle routine di lettura e scrittura sui file, ma in realtà non viene occupato spazio sul filesystem.

Per utilizzare tale meccanismo di IPC è necessario quindi che i processi possano condividere i file descriptor associati alla pipe, pertanto essi devono comunque derivare dallo stesso processo padre in cui è avveuta la creazione della pipe (in tal caso i processi sono detti sibling) o essere uno il figlio dell’altro.