Messo nuovo esempio e figura corretta.
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 21fae712f9ee9894e9c5061670b5b847cd8c4cbc..40c9fadd4c20f23f608497e443a65a2972107868 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1,4 +1,4 @@
-f\chapter{La comunicazione fra processi}
+\chapter{La comunicazione fra processi}
 \label{cha:IPC}
 
 
@@ -86,23 +86,22 @@ 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}
 
 Tutto ciò ci mostra come sia immediato realizzare un meccanismo di
 comunicazione fra processi attraverso una pipe, utilizzando le ordinarie
 proprietà dei file, ma ci mostra anche qual'è il principale\footnote{Stevens
-  riporta in APUE come limite anche il fatto che la comunicazione è
-  unidirezionale, in realtà questo è un limite facilmente risolvibile usando
+  in \cite{APUE} riporta come limite anche il fatto che la comunicazione è
+  unidirezionale, in realtà questo è un limite facilmente superabile usando
   una coppia di pipe.} limite nell'uso delle pipe. È necessario infatti che i
 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.
 
 
-
 \subsection{Un esempio dell'uso delle pipe}
 \label{sec:ipc_pipe_use}
 
@@ -110,45 +109,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-bin}\footnote{breve descrizione, da fare, di cosa è un cgi-bin.}
-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-bin} 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:
+\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} 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-bin} 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 processi, e 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.
+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{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_barcode_code}
+abbiamo riportato il corpo del programm, il cui codice completo è disponibile
+nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti.
 
 
 \begin{figure}[!htb]
@@ -167,87 +179,112 @@ int main(int argc, char *argv[], char *envp[])
         WriteMess("output pipe creation error");
         exit(0);        
     }    
-    /* fork child to run barcode program */
-    pid = fork();
-    if (pid == -1) {
+    /* First fork: use child to run barcode program */
+    if ( (pid = fork()) == -1) {          /* on error exit */
         WriteMess("child creation error");
         exit(0);        
     }
     /* if child */
     if (pid == 0) {
-        close(pipein[1]);        /* close output side of input pipe */
-        dup2(0, pipein[0]);      /* remap stdin in pipe input */
-        close(pipeout[0]);       /* close input side of output pipe */
-        dup2(1, pipeout[1]);     /* remap stdout in pipe output */
-        execlp("barcode", "barcode", "-E", NULL);
-    } else { 
-        /* first set the pipe */
-        close(pipein[0]);        /* close input side of input pipe */
-        close(pipeout[1]);       /* close output side of output pipe */
-        write(pipein[1], argv[1], strlen(argv[1]));
-        close(pipein[1]);
-        waitpid(pid, NULL, 0);
-        pid = fork();
-        if (pid == -1) {
-            WriteMess("child creation error")
-            exit(0);
-        }
-        if (pid == 0) {
-            /* send mime type */
-            write(0,content, strlen(content));
-            dup2(0, pipeout[0]);
-            execlp("gs", "gs", "-sDEVICE=jpeg", "-sOutputFile=-", "-", NULL);
-        } else {
-            close(pipeout[0]);
-            waitpid(pid, NULL, 0);
-        }
+        close(pipein[1]);                /* close pipe write end  */
+        dup2(pipein[0], STDIN_FILENO);   /* remap stdin to pipe read end */
+        close(pipeout[0]);
+        dup2(pipeout[1], STDOUT_FILENO); /* remap stdout in pipe output */
+        execlp("barcode", "barcode", size, NULL); //"-o", "-",  NULL);
+    } 
+    close(pipein[0]);                    /* close input side of input pipe */
+    write(pipein[1], argv[1], strlen(argv[1]));  /* write parameter to pipe */
+    close(pipein[1]);                    /* closing write end */
+    waitpid(pid, NULL, 0);               /* wait child completion */
+    /* Second fork: use child to run ghostscript */
+    if ( (pid = fork()) == -1) {          /* on error exit */
+        WriteMess("child creation error");
+        exit(0);
+    }
+    /* second child, convert PS to JPEG  */
+    if (pid == 0) {                     
+        close(pipeout[1]);              /* close write end */
+        dup2(pipeout[0], STDIN_FILENO); /* remap read end to stdin */
+        /* send mime type */
+        write(STDOUT_FILENO, content, strlen(content));
+        execlp("gs", "gs", "-q", "-sDEVICE=jpeg", "-sOutputFile=-", "-", NULL);
     }
+    /* still parent */
+    close(pipeout[1]); 
+    waitpid(pid, NULL, 0);
     exit(0);
 }
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{Codice del \textit{cgi-bin} \cmd{BarCode}.}
+  \caption{Codice del \textit{CGI} \cmd{BarCodePage}.}
   \label{fig:ipc_barcode_code}
 \end{figure}
 
-
-Il primo passo (\texttt{\small 4-12}) è quello di creare le due pipe, una per
-l'input e l'altra per l'output, che servono per la comunicazione con i due
-programmi che verranno utilizzati, inviando in caso di errore (attraverso una
-apposita funzione \func{WriteMess}, non riportata in
-\ref{fig:ipc_barcode_code}, che si incarica di formattare l'output in HTML
-perché sia interpretabile da un browser) un messaggio invece dell'immagine
-richiesta.
-
-Una volta create le pipe il programma può creare (\texttt{\small 13-18}) il
-primo processo figlio, che si incaricherà (\texttt{\small 19-25}) di eseguire
-\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 questo il processo figlio prima chiude (\texttt{\small 21}) il capo aperto
-in scrittura della prima pipe (che sarà usato dal padre per trasmettergli la
-stringa da codificare), e poi collega (\texttt{\small 22}) il capo il lettura
-allo standard input usando \func{dup2}.  Analogamente il capo in lettura della
-seconda pipe sarà chiuso mentre il capo in scrittura viene collegato allo
-standard output (\texttt{\small 23-24}.  In questo modo all'esecuzione
-(\texttt{\small 25}) di \cmd{barcode} quest'ultimo leggerà la stringa da
-codificare dalla prima pipe e scriverà l'immagine postscript nella seconda.
-
-Dall'altra parte il processo padre prima chiude (\texttt{\small 28-29}) i due
-capi inutilizzati delle pipe (input della prima ed output della seconda), poi
-scrive (\texttt{\small 30}) la stringa da convertire sull'output della prima
-pipe 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 31}), si attenderà poi (\texttt{\small 32}) che
-l'esecuzione di \cmd{barcode} venga completata.
-
-Alla conclusione della sua esecuzione \cmd{barcode} avrà effettuato inviato
-l'immagine postscript del codice a barre sul capo in scrittura della seconda
-pipe; a questo punto 
-
-
+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
+  \secref{fig:ipc_barcode_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
+primo processo figlio, che si incaricherà (\texttt{\small 19--25}) di eseguire
+\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}. 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}).
+
+In questo modo all'esecuzione (\texttt{\small 25}) di \cmd{barcode} (cui si
+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 è 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
+questo punto si può eseguire la seconda conversione, da PS a JPEG, usando il
+programma \cmd{gs}. Per questo si crea (\texttt{\small 30--34}) un secondo
+processo figlio, che poi (\texttt{\small 35--42}) eseguirà questo programma
+leggendo l'immagine postscript creata da \cmd{barcode} dallo standard input,
+per convertirla in JPEG.
+
+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}); a questo punto può \texttt{\small 46}). 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}}
@@ -256,36 +293,210 @@ pipe; a questo punto
 Come si è visto la modalità più comune di utilizzo di una pipe è quella di
 utilizzarla per fare da tramite fra output ed input di due programmi invocati
 in sequenza; per questo motivo lo standard POSIX.2 ha introdotto due funzioni
-che permettono di sintetizzare queste operazioni comuni in una sola
-chiamata. La prima di esse si chiama \func{popen} ed il suo prototipo è:
+che permettono di sintetizzare queste operazioni. La prima di esse si chiama
+\func{popen} ed il suo prototipo è:
+\begin{prototype}{stdio.h}
+{FILE *popen(const char *command, const char *type)}
+
+Esegue il programma \param{command}, di cui, a seconda di \param{type},
+restituisce, lo standard input o lo standard output nella pipe collegata allo
+stream restituito come valore di ritorno.
+  
+\bodydesc{La funzione restituisce l'indirizzo dello stream associato alla pipe
+  in caso di successo e \macro{NULL} per un errore, nel qual caso \var{errno}
+  potrà assumere i valori relativi alle sottostanti invocazioni di \func{pipe}
+  e \func{fork} o \macro{EINVAL} se \param{type} non è valido.}
+\end{prototype}
 
+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 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
+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
+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)}
+
+Chiude il file \param{stream}, restituito da una prededente \func{popen}
+attendendo la terminazione del processo ad essa associato.
+  
+\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+  errore; nel quel caso il valore di \func{errno} deriva dalle sottostanti
+  chiamate.}
+\end{prototype}
+\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 riprenderemo il problema
+precedente; il programma mostrato in \figref{fig:ipc_barcode_code} per quanto
+funzionante, è (volutamente) codificato in maniera piuttosto complesso;
+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 semplice figura delle dimensioni
+corrispondenti al codice a barre.
+
+Se si vuole generare una immagine di dimensioni corrette si deve usare un
+approccio diverso; una possibilità sarebbe quella di ricorrere ad ulteriore
+programma, \cmd{epstopsf}, per convertire in PDF il file EPS generato da
+\cmd{barcode} (utilizzando lo switch \cmd{-E} di quest'ultimo). 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; una pipe però è rigidamente sequenziale,
+ed il tentativo di eseguire detta funzioni su un file descriptor associato ad
+una pipe comporta l'immediato fallimento con un errore di \macro{ESPIPE}.
+
+Per questo motivo si è utilizzata 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.
+
+In questo caso però occorre eseguire sequenza ben quattro comandi diversi,
+inviando l'output di ciascuno all'input del successivo, per poi ottenere il
+risultato finale sullo standard output, il caso più classico dell'uso delle
+pipe. 
+
+
+Dato che questo caso 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.
 
-L'esempio in \figref{fig:ipc_barcode_code} per quanto perfettamente
-funzionante, è piuttosto complesso; 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}, che invece viene trattato correttamente.
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[], char *envp[])
+{
+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);
+}
+/*
+ * Routine to produce an HTML error message on output 
+ */
+void WriteMess(char *mess)
+{
+    printf("Content-type: text/html\n\n");
+    perror(mess);
+    printf("<br>\n");
+}
+}
 
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice del \textit{cgi-bin} \cmd{BarCode2}.}
+  \label{fig:ipc_barcode2_code}
+\end{figure}
 
+Nel nostro caso il primo passo (\texttt{\small 12}) è 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.
 
+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.
 
+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}.
 
 
 \subsection{Le \textit{pipe} con nome, o \textit{fifo}}
 \label{sec:ipc_named_pipe}
 
-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, lo standard POSIX.1
-definisce dei nuovi oggetti, le \textit{fifo}, che invece possono risiedere
+Come accennato in \secref{sec:ipc_pipes} il problema delle \textit{pipe} è che
+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.
 
 
 
+
+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}