Completate pure le fifo.
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index e5631536c274f154f1304afa51cb82241931b9e3..cd9c68fed1b9596b3bf07e68eb041f09b5aa82df 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -86,8 +86,8 @@ capo della pipe, l'altro pu
 \begin{figure}[htb]
   \centering
   \includegraphics[height=5cm]{img/pipefork}
-  \caption{Schema dell'uso di una pipe come mezzo di comunicazione fra
-  processo attraverso una \func{fork}.}
+  \caption{Schema dei collegamenti ad una pipe, condivisi fra processo padre e
+    figlio dopo l'esecuzione \func{fork}.}
   \label{fig:ipc_pipe_fork}
 \end{figure}
 
@@ -101,6 +101,16 @@ processi possano condividere i file descriptor della pipe, e per questo essi
 devono comunque derivare da uno stesso processo padre che ha aperto la pipe,
 o, più comunemente, essere nella relazione padre/figlio.
 
+A differenza di quanto avviene con i file normali la lettura da una pipe può
+essere bloccante (qualora non siano presenti dati), inoltre se si legge da una
+pipe il cui capo in scrittura è stato chiuso, si avrà la ricezione di un EOF
+(vale a dire che la funzione \func{read} ritornerà restituendo 0).  Se invece
+si esegue una scrittura su una pipe il cui capo in lettura non è aperto il
+processo riceverà il segnale \macro{EPIPE}, e la funzione di scrittura
+restituirà un errore di \macro{EPIPE} (al ritorno del manipolatore, o qualora
+il segnale sia ignorato o bloccato).
+
+
 
 \subsection{Un esempio dell'uso delle pipe}
 \label{sec:ipc_pipe_use}
@@ -109,45 +119,58 @@ Per capire meglio il funzionamento di una pipe faremo un esempio di quello che
 è il loro uso più comune, analogo a quello effettuato della shell, e che
 consiste nell'inviare l'output di un processo (lo standard output) sull'input
 di un'altro. Realizzaremo il programma nella forma di un
-\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface} è un programma
+\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un programma
   che permette la creazione dinamica di un oggetto da inserire all'interno di
   una pagina HTML.}  per apache, che genera una immagine JPEG di un codice a
 barre, specificato come parametro di input.
 
-Un programma che deve essere eseguito come \textit{cgi} per apache deve
-rispondere a delle caratteristiche specifiche, esso infatti non viene lanciato
-da una shell, ma dallo stesso web server, alla richiesta di una specifica URL
-che di solito ha la forma:
+Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
+delle caratteristiche specifiche, esso infatti non viene lanciato da una
+shell, ma dallo stesso web server, alla richiesta di una specifica URL, che di
+solito ha la forma:
 \begin{verbatim}
-http://www.sito.it/cgi-bin/programma?parametro
+    http://www.sito.it/cgi-bin/programma?parametro
 \end{verbatim}
 ed il risultato dell'elaborazione deve essere presentato (con una intestazione
-che ne descrive il mime-type) sullo standard output, in modo che apache possa
-reinviarlo al browser che ha effettuato la richiesta.
+che ne descrive il mime-type) sullo standard output, in modo che il web-server
+possa reinviarlo al browser che ha effettuato la richiesta, che in questo modo
+è in grado di visualizzarlo opportunamente.
 
 Per fare questo useremo in sequenza i programmi \cmd{barcode} e \cmd{gs}, il
 primo infatti è in grado di generare immagini postscript di codici a barre
 corrispondenti ad una qualunque stringa, mentre il secondo serve per poter
-effettuare la conversione della stessa immagine in formato JPEG.
+effettuare la conversione della stessa immagine in formato JPEG. Usando una
+pipe potremo inviare l'output del primo sull'input del secondo, secondo lo
+schema mostrato in \figref{fig:ipc_pipe_use}, in cui la direzione del flusso
+dei dati è data dalle frecce continue.
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[height=5cm]{img/pipeuse}
+  \caption{Schema dell'uso di una pipe come mezzo di comunicazione fra
+    due processi attraverso attraverso l'esecuzione una \func{fork} e la
+    chiusura dei capi non utilizzati.}
+  \label{fig:ipc_pipe_use}
+\end{figure}
 
 Si potrebbe obiettare che sarebbe molto più semplice salvare il risultato
-intermedio su un file temporaneo. Questo però non tiene conto del fatto che il
-\textit{cgi} deve poter gestire più richieste in concorrenza, e si avrebbe una
+intermedio su un file temporaneo. Questo però non tiene conto del fatto che un
+\textit{CGI} deve poter gestire più richieste in concorrenza, e si avrebbe una
 evidente race condition in caso di accesso simultaneo a detto
-file.\footnote{la questione potrebbe essere evitata creando prima dei file
-  temporanei, da comunicare poi ai vari sotto-processi, da cancellare alla
-  fine dell'esecuzione; ma a questo punto avremmo perso tutta la semplicità.}
-L'uso di una pipe invece permette di risolvere il problema in maniera semplice
-ed elegante.
-
-Il programma ci servirà anche come esempio dell'uso di alcune delle funzioni
-di manipolazione dei file descriptor, come \func{dup} e \func{dup2}, viste in
-\secref{sec:file_dup}; è attraverso queste funzioni che è possibile dirottare
-gli stream standard dei processi (che abbiamo visto in
-\secref{sec:file_std_descr} e \secref{sec:file_std_stream}) sulla pipe. Le
-sezioni significative del programma è riportato in
-\figref{fig:ipc_barcode_code}, il codice è disponibile nel file
-\file{BarCode.c} nella directory dei sorgenti.
+file.\footnote{il problema potrebbe essere superato determinando in anticipo
+  un nome appropiato per il file temporaneo, che verrebbe utilizzato dai vari
+  sotto-processi, e cancellato alla fine della loro esecuzione; ma a questo le
+  cose non sarebbero più tanto semplici.}  L'uso di una pipe invece permette
+di risolvere il problema in maniera semplice ed elegante.
+
+Il programma ci servirà anche come esempio dell'uso delle funzioni di
+duplicazione dei file descriptor che abbiamo trattato in
+\secref{sec:file_dup}, in particolare di \func{dup2}. È attraverso queste
+funzioni infatti che è possibile dirottare gli stream standard dei processi
+(che abbiamo visto in \secref{sec:file_std_descr} e
+\secref{sec:file_std_stream}) sulla pipe. In \figref{fig:ipc_barcodepage_code}
+abbiamo riportato il corpo del programma, il cui codice completo è disponibile
+nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti.
 
 
 \begin{figure}[!htb]
@@ -204,47 +227,50 @@ int main(int argc, char *argv[], char *envp[])
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{Codice del \textit{cgi-bin} \cmd{BarCode}.}
-  \label{fig:ipc_barcode_code}
+  \caption{Sezione principale del codice del \textit{CGI} 
+    \file{BarCodePage.c}.}
+  \label{fig:ipc_barcodepage_code}
 \end{figure}
 
-Il primo passo (\texttt{\small 4--12}) è quello di creare le due pipe che
-servono per la comunicazione fra i due programmi che verranno utilizzati per
-produrre il codice a barre; si ha cura di controllare la riuscita della
+La prima operazione del programma (\texttt{\small 4--12}) è quella di creare
+le due pipe che serviranno per la comunicazione fra i due comandi utilizzati
+per produrre il codice a barre; si ha cura di controllare la riuscita della
 chiamata, inviando in caso di errore un messaggio invece dell'immagine
 richiesta.\footnote{la funzione \func{WriteMess}, non è riportata in
-  \ref{fig:ipc_barcode_code}, ma si incarica semplicemente di formattare
-  l'uscita, aggiungendo un \textit{mime type}, in modo che possa essere
-  interpretata direttamente da un browser.}
+  \secref{fig:ipc_barcodepage_code}; essa si incarica semplicemente di
+  formattare l'uscita alla maniera dei CGI, aggiungendo l'opportuno
+  \textit{mime type}, e formattando il messaggio in HTML, in modo che
+  quest'ultimo possa essere visualizzato correttamente da un browser.}
 
-Una volta create le pipe il programma può creare (\texttt{\small 13-17}) il
+Una volta create le pipe, il programma può creare (\texttt{\small 13-17}) il
 primo processo figlio, che si incaricherà (\texttt{\small 19--25}) di eseguire
-il programma \cmd{barcode}: quest'ultimo funziona ricevendo dallo standard
-input la stringa da convertire nell'immagine postscript del codice a barre,
-che sarà scritta sullo standard output.
-
-Per utilizzare queste caratteristiche il primo figlio chiude (\texttt{\small
-  20}) il capo aperto in scrittura della prima pipe, dato che userà il capo
-aperto in lettura per ricevere dal padre la stringa da codificare; per far
-questo collega (\texttt{\small 21}) il capo in lettura della pipe allo
-standard input usando \func{dup2}. Dato che \cmd{barcode} scrive l'immagine
-postscript del codice a barre sullo standard output per poter effettuare una
+\cmd{barcode}. Quest'ultimo legge dallo standard input una stringa di
+caratteri, la converte nell'immagine postscript del codice a barre ad essa
+corrispondente, e poi scrive il risultato direttamente sullo standard output.
+
+Per poter utilizzare queste caratteristiche prima di eseguire \cmd{barcode} si
+chiude (\texttt{\small 20}) il capo aperto in scrittura della prima pipe, e se
+ne collega (\texttt{\small 21}) il capo in lettura allo standard input, usando
+\func{dup2}. Si ricordi che invocando \func{dup2} il secondo file, qualora
+risulti aperto, viene, come nel caso corrente, chiuso prima di effettuare la
+duplicazione. Allo stesso modo, dato che \cmd{barcode} scrive l'immagine
+postscript del codice a barre sullo standard output, per poter effettuare una
 ulteriore redirezione il capo in lettura della seconda pipe viene chiuso
 (\texttt{\small 22}) mentre il capo in scrittura viene collegato allo standard
-output (\texttt{\small 23}).  
+output (\texttt{\small 23}).
 
 In questo modo all'esecuzione (\texttt{\small 25}) di \cmd{barcode} (cui si
-passa in \var{size} la dimensione per l'immagine) quest'ultimo leggerà la
-stringa da codificare che gli viene inviata dal padre dalla prima pipe e
-scriverà l'immagine postscript del codice a barre sulla seconda.
-
-Dall'altra parte il processo padre prima chiude (\texttt{\small 26}) il capo
-inutilizzato della prima pipe (quello in input), poi scrive (\texttt{\small
-  27}) la stringa da convertire sul capo in output, così che \cmd{barcode}
-possa riceverla dallo standard input; a questo punto l'uso della prima pipe è
-finito ed essa può essere definitivamente chiusa (\texttt{\small 28}), si
-attende poi (\texttt{\small 29}) che l'esecuzione di \cmd{barcode} sia
-completata.
+passa in \var{size} la dimensione della pagina per l'immagine) quest'ultimo
+leggerà dalla prima pipe la stringa da codificare che gli sarà inviata dal
+padre, e scriverà l'immagine postscript del codice a barre sulla seconda.
+
+Al contempo una volta lanciato il primo figlio, il processo padre prima chiude
+(\texttt{\small 26}) il capo inutilizzato della prima pipe (quello in input) e
+poi scrive (\texttt{\small 27}) la stringa da convertire sul capo in output,
+così che \cmd{barcode} possa riceverla dallo standard input. A questo punto
+l'uso della prima pipe da parte del padre è finito ed essa può essere
+definitivamente chiusa (\texttt{\small 28}), si attende poi (\texttt{\small
+  29}) che l'esecuzione di \cmd{barcode} sia completata.
 
 Alla conclusione della sua esecuzione \cmd{barcode} avrà inviato l'immagine
 postscript del codice a barre sul capo in scrittura della seconda pipe; a
@@ -254,24 +280,25 @@ processo figlio, che poi (\texttt{\small 35--42}) eseguir
 leggendo l'immagine postscript creata da \cmd{barcode} dallo standard input,
 per convertirla in JPEG.
 
-Per fare tutto ciò il secondo figlio anzitutto chiude (\texttt{\small 37}) il
-capo in scrittura della seconda pipe, e ne collega (\texttt{\small 38}) il
-capo in lettura allo standard input. Per poter formattare l'output del
-programma in maniera utilizzabile da un browser, si provvede anche
-\texttt{\small 40}) alla scrittura dell'apposita stringa di mime-type in testa
-allo standard output. A questo punto si può invocare \texttt{\small 41}) il
-programma \cmd{gs}, provvedendo gli appositi switch che consentono di leggere
-il file da convertire dallo standard input, ed inviare la conversione sullo
-standard output.
-
-Per concludere le operazioni il processo padre chiude \texttt{\small 44}) il
+Per fare tutto ciò anzitutto si chiude (\texttt{\small 37}) il capo in
+scrittura della seconda pipe, e se ne collega (\texttt{\small 38}) il capo in
+lettura allo standard input. Per poter formattare l'output del programma in
+maniera utilizzabile da un browser, si provvede anche \texttt{\small 40}) alla
+scrittura dell'apposita stringa di identificazione del mime-type in testa allo
+standard output. A questo punto si può invocare \texttt{\small 41}) \cmd{gs},
+provvedendo gli appositi switch che consentono di leggere il file da
+convertire dallo standard input e di inviare la conversione sullo standard
+output.
+
+Per completare le operazioni il processo padre chiude (\texttt{\small 44}) il
 capo in scrittura della seconda pipe, e attende la conclusione del figlio
-\texttt{\small 45}), per poi uscire \texttt{\small 46}). Si tenga conto che,
-l'operazione di chiudere il capo in scrittura della seconda pipe è necessaria,
-infatti non chiudendola \cmd{gs}, che legge il suo stardard input da detta
-pipe, resterebbe bloccato in attesa di ulteriore input (l'unico modo che un
-programma ha per sapere che l'input è terminato è rilevare che lo standard
-input è stato chiuso), e la \func{wait} non ritornerebbe. 
+(\texttt{\small 45}); a questo punto può (\texttt{\small 46}) uscire. Si tenga
+conto che l'operazione di chiudere il capo in scrittura della seconda pipe è
+necessaria, infatti, se non venisse chiusa, \cmd{gs}, che legge il suo
+stardard input da detta pipe, resterebbe bloccato in attesa di ulteriori dati
+in ingresso (l'unico modo che un programma ha per sapere che l'input è
+terminato è rilevare che lo standard input è stato chiuso), e la \func{wait}
+non ritornerebbe.
 
 
 \subsection{Le funzioni \func{popen} e \func{pclose}}
@@ -294,13 +321,12 @@ stream restituito come valore di ritorno.
   potrà assumere i valori relativi alle sottostanti invocazioni di \func{pipe}
   e \func{fork} o \macro{EINVAL} se \param{type} non è valido.}
 \end{prototype}
-\noindent e serve per semplificare l'uso di \func{pipe}. 
 
 La funzione crea una pipe, esegue una \func{fork}, ed invoca il programma
 \param{command} attraverso la shell (in sostanza esegue \file{/bin/sh} con il
-flag \code{-c}); l'argomento \param{type} deve essere una stringa \verb|"w"| o
-\verb|"r"|, per indicare se la pipe sarà collegata allo standard input o allo
-standard output del comando invocato.
+flag \code{-c}); l'argomento \param{type} deve essere una delle due stringhe
+\verb|"w"| o \verb|"r"|, per indicare se la pipe sarà collegata allo standard
+input o allo standard output del comando invocato.
 
 La funzione restituisce il puntatore allo stream associato alla pipe creata,
 che sarà aperto in sola lettura (e quindi associato allo standard output del
@@ -308,10 +334,11 @@ programma indicato) in caso si sia indicato \code{"r"}, o in sola scrittura (e
 quindi associato allo standard input) in caso di \code{"w"}.
 
 Lo stream restituito da \func{popen} è identico a tutti gli effetti ai file
-standard visti in \secref{cha:files_std_interface}, e viene sempre aperto in
-modalità \textit{fully-buffered} (vedi \secref{sec:file_buffering}); l'unica
-differenza è che deve essere chiuso dalla seconda delle due funzioni,
-\func{pclose}, il cui prototipo è:
+stream visti in \secref{cha:files_std_interface}, anche se è collegato ad una
+pipe e non ad un inode, e viene sempre aperto in modalità
+\textit{fully-buffered} (vedi \secref{sec:file_buffering}); l'unica differenza
+con gli usuali stream è che dovrà essere chiuso dalla seconda delle due nuove
+funzioni, \func{pclose}, il cui prototipo è:
 \begin{prototype}{stdio.h}
 {int pclose(FILE *stream)}
 
@@ -322,34 +349,61 @@ attendendo la terminazione del processo ad essa associato.
   errore; nel quel caso il valore di \func{errno} deriva dalle sottostanti
   chiamate.}
 \end{prototype}
-\noindent che si incarica anche di attendere la conclusione del processo
-creato dalla precedente \func{popen}.
-
-Per illustrare l'uso di queste due funzioni riprendiamo l'esempio in
-\figref{fig:ipc_barcode_code}: esso per quanto funzionante, è piuttosto
-complesso; inoltre nella pratica sconta un problema di \cmd{gs} che non è in
+\noindent che oltre alla chiusura dello stream si incarica anche di attendere
+(tramite \func{wait4}) la conclusione del processo creato dalla precedente
+\func{popen}.
+
+Per illustrare l'uso di queste due funzioni riprendiamo il problema
+precedente: il programma mostrato in \figref{fig:ipc_barcodepage_code} per
+quanto funzionante, è (volutamente) codificato in maniera piuttosto complessa,
+inoltre nella pratica sconta un problema di \cmd{gs} che non è in
 grado\footnote{nella versione GNU Ghostscript 6.53 (2002-02-13).} di
-riconoscere correttamente l'encapsulated postscript, per cui tutte le volte
-generata una pagina intera, invece che una semplice figura.  Se si vuole
-generare una immagine di dimensioni corrette si deve allora ricorrere ad
-ulteriore programma, \cmd{epstopsf}, per convertire in PDF il file EPS
-generato da \cmd{barcode}. Utilizzando un file in PDF invece, \cmd{gs} esegue
-la conversione rispettando le dimensioni originarie del codice a barre.
-
-Ci si trova dunque davanti al classico caso dell'uso delle pipe in cui si
-devono eseguire più processi in fila, inviando l'output di ciascuno all'input
-del successivo, per poi ottenere il risultato finale sullo standard output.
-Dato che questo caso ciascun processo deve scrivere il suo output sullo
+riconoscere correttamente l'encapsulated postscript, per cui deve essere usato
+il postscript e tutte le volte viene generata una pagina intera, invece che
+una immagine delle dimensioni corrispondenti al codice a barre.
+
+Se si vuole generare una immagine di dimensioni appropriate si deve usare un
+approccio diverso. Una possibilità sarebbe quella di ricorrere ad ulteriore
+programma, \cmd{epstopsf}, per convertire in PDF un file EPS (che può essere
+generato da \cmd{barcode} utilizzando lo switch \cmd{-E}).  Utilizzando un PDF
+al posto di un EPS \cmd{gs} esegue la conversione rispettando le dimensioni
+originarie del codice a barre e produce un JPEG delle dimensioni adeguate.
+
+Questo però ci porta a scontrarci con una caratteristica peculiare delle pipe,
+che a prima vista non è evidente. Per poter effettuare la conversione di un
+PDF infatti è necessario, per la struttura del formato, dover eseguire delle
+\func{lseek} sul file da convertire; se si esegue \cmd{gs} su un file normale
+non ci sono problemi, ma una pipe però è rigidamente sequenziale, ed il
+tentativo di eseguire detta operazione su una pipe comporta l'immediato
+fallimento con un errore di \macro{ESPIPE}.  Questo ci dice che in generale la
+concatenazione di vari programmi funzionerà soltanto quando tutti prevedono
+una lettura sequenziale del loro input.
+
+Per questo motivo si è dovuto utilizzare una strada diversa, che prevede la
+conversione attraverso \cmd{gs} del PS in un altro formato intermedio, il
+PPM,\footnote{il \textit{Portable PixMap file format} è un formato usato
+  spesso come formato intermedio per effettuare conversioni, è estremamente
+  inefficiente, ma molto facile da manipolare dato che usa caratteri ASCII per
+  memorizzare le immagini.} dal quale poi si può ottenere un'immagine di
+dimensioni corrette attraverso vari programmi di manipolazione (\cmd{pnmcrop},
+\cmd{pnmmargin}) che può essere infine trasformata in PNG (con \cmd{pnm2png}).
+
+In questo caso però occorre eseguire in sequenza ben quattro comandi diversi,
+inviando l'output di ciascuno all'input del successivo, per poi ottenere il
+risultato finale sullo standard output: un caso classico di utilizzazione
+delle pipe, in cui l'uso di \func{popen} e \func{pclose} permette di
+semplificare notevolmente la stesura del codice.
+
+Nel nostro caso, dato che ciascun processo deve scrivere il suo output sullo
 standard input del successivo, occorrerà usare \func{popen} aprendo la pipe in
-scrittura.
-
-Il codice del nuovo programma è riportato in \figref{fig:ipc_barcode2_code};
-come si può notare l'ordine di invocazione dei programmi è l'inverso di quello
-in cui ci si aspetta vengano effettivamente eseguiti. Questo non comporta
-nessun problema; infatti la lettura su una pipe è bloccante, per cui ciascun
-processo, per quanto lanciato per primo, si bloccherà in attesa di ricevere
-sullo standard input il risultato dell'elaborazione del precendente, benchè
-quest'ultimo venga invocato dopo.
+scrittura. Il codice del nuovo programma è riportato in
+\figref{fig:ipc_barcode_code}.  Come si può notare l'ordine di invocazione dei
+programmi è l'inverso di quello in cui ci si aspetta che vengano
+effettivamente eseguiti. Questo non comporta nessun problema dato che la
+lettura su una pipe è bloccante, per cui ciascun processo, per quanto lanciato
+per primo, si bloccherà in attesa di ricevere sullo standard input il
+risultato dell'elaborazione del precendente, benchè quest'ultimo venga
+invocato dopo.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -357,33 +411,62 @@ quest'ultimo venga invocato dopo.
     \begin{lstlisting}{}
 int main(int argc, char *argv[], char *envp[])
 {
+    FILE *pipe[4];
+    FILE *pipein;
+    char *cmd_string[4]={
+        "pnmtopng",
+        "pnmmargin -white 10",
+        "pnmcrop",
+        "gs -sDEVICE=ppmraw -sOutputFile=- -sNOPAUSE -q - -c showpage -c quit"
+    };  
+    char content[]="Content-type: image/png\n\n";
+    int i;
+    /* write mime-type to stout */ 
+    write(STDOUT_FILENO, content, strlen(content));
+    /* execute chain of command */
+    for (i=0; i<4; i++) {
+        pipe[i] = popen(cmd_string[i], "w");
+        dup2(fileno(pipe[i]), STDOUT_FILENO); 
+    }
+    /* create barcode (in PS) */
+    pipein = popen("barcode", "w");
+    /* send barcode string to barcode program */
+    write(fileno(pipein), argv[1], strlen(argv[1]));
+    /* close all pipes (in reverse order) */
+    for (i=4; i==0; i--) {
+        pclose((pipe[i]));
+    }
+    exit(0);
 }
-
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{Codice del \textit{cgi-bin} \cmd{BarCode2}.}
-  \label{fig:ipc_barcode2_code}
+  \caption{Codice completo del \textit{CGI} \file{BarCode.c}.}
+  \label{fig:ipc_barcode_code}
 \end{figure}
 
-Nel nostro caso il primo passo (\texttt{\small 12}) è scrivere il mime-type
+Nel nostro caso il primo passo (\texttt{\small 14}) è scrivere il mime-type
 sullo standard output; a questo punto il processo padre non necessita più di
 eseguire ulteriori operazioni sullo standard output e può tranquillamente
-provvedere alla redirezione. Il primo processo figlio ad essere invocato
-(\texttt{\small 14}) è necessariamente l'ultimo della sequenza, in quanto è
-lui che deve uscire sullo standard output, gli altri saranno tutti rediretti.
+provvedere alla redirezione.
 
-Una volta lanciato il processo finale si può iniziare la catena delle
-redirezioni; ogni volta (\texttt{\small 16} e \texttt{\small 20}) duplicheremo
-il file restituito dalla chiamata precedente a \func{popen} sullo standard
-output, in questo modo alla successiva chiamata di \func{popen} il processo
-eseguito scriverà il suo standard output sulla pipe collegata allo standard
-input del precedente.
+Dato che i vari programmi devono essere lanciati in successione, si è
+approntato un ciclo (\texttt{\small 15--19}) che esegue le operazioni in
+sequenza: prima crea una pipe (\texttt{\small 17}) per la scrittura eseguendo
+il programma con \func{popen}, in modo che essa sia collegata allo standard
+input, e poi redirige (\texttt{\small 18}) lo standard output su detta pipe.
 
-Alla fine tutto quello che resta da fare è scrivere (\texttt{\small 22}) la
-stringa del codice a barre sulla pipe collegata allo standard input
-dell'ultimo processo lanciato, e poi chiudere tutte le pipe create con
-\func{pclose}.
+In questo modo il primo processo ad essere invocato (che è l'ultimo della
+catena) scriverà ancora sullo standard output del processo padre, ma i
+successivi, a causa di questa redirezione, scriveranno sulla pipe associata
+allo standard input del processo invocato nel ciclo precedente.
+
+Alla fine tutto quello che resta da fare è lanciare (\texttt{\small 21}) il
+primo processo della catena, che nel caso è \cmd{barcode}, e scrivere
+(\texttt{\small 23}) la stringa del codice a barre sulla pipe, che è collegata
+al suo standard input, infine si può eseguire (\texttt{\small 24--27}) un
+ciclo, che chiuda, nell'ordine inverso rispetto a quello in cui le si sono
+create, tutte le pipe create con \func{pclose}.
 
 
 \subsection{Le \textit{pipe} con nome, o \textit{fifo}}
@@ -393,33 +476,47 @@ Come accennato in \secref{sec:ipc_pipes} il problema delle \textit{pipe} 
 esse possono essere utilizzate solo da processi con un progenitore comune o
 nella relazione padre/figlio; per superare questo problema lo standard POSIX.1
 ha definito dei nuovi oggetti, le \textit{fifo}, che hanno le stesse
-caratteristiche delle pipe, ma invece che essere struttura interne del kernel
-visibili solo attraverso un file descriptor comune, possono essere viste
-attraverso un inode che risiede sul filesystem.
-
-Utilizzando una fifo tutti i dati passeranno attraverso un apposito buffer nel
-kernel, senza transitare dal filesystem, l'inode serve solo a fornire un punto
-d'appoggio per i vari processi che permetta loro di accedere alla stessa
-fifo.  
-
-
-
-
-Abbiamo già visto in \secref{sec:file_mknod} le modalità che permettono di
-creare una fifo, attraverso le funzioni \func{mknod} e \func{mkfifo}; per
-utilizzarle un processo non avrà che da aprire il relativo file in lettura o
-scrittura (a seconda della direzione che si vuole dare ai dati).
-
-che invece possono risiedere
-sul filesystem, e che i processi possono usare per le comunicazioni senza
-dovere per forza essere in relazione diretta.
-
-
+caratteristiche delle pipe, ma che invece di essere strutture interne del
+kernel, visibili solo attraverso un file descriptor, sono accessibili
+attraverso un inode che risiede sul filesystem, così che i processi le possono
+usare senza dovere per forza essere in una relazione di \textsl{parentela}.
+
+Utilizzando una \textit{fifo} tutti i dati passeranno, come per le pipe,
+attraverso un apposito buffer nel kernel, senza transitare dal filesystem;
+l'inode allocato sul filesystem serve infatti solo a fornire un punto di
+riferimento per i processi, che permetta loro di accedere alla stessa fifo; il
+comportamento delle funzioni di lettura e scrittura è identico a quello
+illustrato per le pipe in \secref{sec:ipc_pipes}.
+
+Abbiamo già visto in \secref{sec:file_mknod} le funzioni \func{mknod} e
+\func{mkfifo} che permettono di creare una fifo; per utilizzarne una un
+processo non avrà che da aprire il relativo file speciale o in lettura o
+scrittura; nel primo caso sarà collegato al capo di uscita della fifo, e dovrà
+leggere, nel secondo al capo di ingresso, e dovrà scrivere.
+
+Il kernel crea una sigola pipe per ciascuna fifo che sia stata aperta, che può
+essere acceduta contemporaneamente da più processi, sia in lettura che in
+scrittura. Dato che per funzionare deve essere aperta in entrambe le
+direzioni, per una fifo di norma la funzione \func{open} si blocca se viene
+eseguita quando l'altro capo non è aperto.
+
+Le fifo però possono essere anche aperte in modalità \textsl{non-bloccante},
+nel qual caso l'apertura del capo in lettura avrà successo solo quando anche
+l'altro capo è aperto, mentre l'apertura del capo in scrittura restituirà
+l'errore di \macro{ENXIO} fintanto che non verrà aperto il capo in lettura.
+
+In Linux\footnote{lo standard POSIX lascia indefinito questo comportamento.} è
+possibile aprire le fifo anche in lettura/scrittura, operazione che avrà
+sempre successo qualunque sia la modalità di apertura (bloccante e non
+bloccante); questo può essere utilizzato per aprire comunque una fifo in
+scrittura anche se non ci sono ancora processi il lettura; è possibile anche
+usare la fifo all'interno di un solo processo, nel qual caso però occorre
+stare molto attenti alla possibili deadlock.\footnote{se si cerca di leggere
+  da una fifo che non contiene dati si avrà un deadlock immediato, dato che il
+  processo si blocca e non potrà quindi mai eseguire le funzioni di
+  scrittura.}
 
 
-Per poter superare il problema delle \textit{pipe}, illustrato in
-\secref{sec:ipc_pipes}, che ne consente l'uso solo fra processi con un
-progenitore comune o nella relazione padre/figlio,
   
 \section{La comunicazione fra processi di System V}
 \label{sec:ipc_sysv}