varie su read/pread/dup/dup2 ecc.
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 21fae712f9ee9894e9c5061670b5b847cd8c4cbc..0b7818c00a9e8ae83a62f18c426ce5f689db6452 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}
 
 
@@ -110,9 +110,9 @@ 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.
+\textit{cgi-bin}\footnote{NdA, inserire una breve descrizione 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
@@ -136,10 +136,10 @@ intermedio su un file temporaneo. Questo per
 \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.
+  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
@@ -167,41 +167,39 @@ 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}
@@ -212,28 +210,34 @@ int main(int argc, char *argv[], char *envp[])
 \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.
+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
+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.}
 
-Una volta create le pipe il programma può creare (\texttt{\small 13-18}) 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
-\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.
+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
+  21}) 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 22}) il capo in 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