varie su read/pread/dup/dup2 ecc.
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 352a7197b9435ea9ff4217540c72efb3ef18dc47..0b7818c00a9e8ae83a62f18c426ce5f689db6452 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -65,7 +65,7 @@ buffer nel kernel, la cui dimensione 
 funzionamento di una pipe è illustrato in \figref{fig:ipc_pipe_singular}, in
 cui sono illustrati i due capi della pipe, associati a ciascun file
 descriptor, con le frecce che indicano la direzione del flusso dei dati
-attaverso la pipe.
+attraverso la pipe.
 
 \begin{figure}[htb]
   \centering
@@ -110,27 +110,171 @@ 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.
-
-Per fare questo useremo 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, data come parametro, mentre il secondo è in grado di
-convertire un file postscript in una immagine JPEG. Usando l'ouptut del primo
-come input del secondo attraverso una pipe potremo generare immagini JPEG del
-codice a barre di una stringa qualunque. 
-
-Si potrebbe obiettare che sarebbe molto più semplice ottenere lo stesso
-risultato salvando il tutto in un file temporaneo, ma si dovrebbe comunque
-risolvere il problema di come comunicare il nome di questo file da un processo
-all'altro, dato che utilizzare lo stesso file porterebbe ad inevitabili
-sovrascritture nell'accavallarsi di diversi processi. L'uso di una pipe
-permette di risolvere il problema in maniera semplice ed elegante.
+\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
+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
+\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.
+
+
+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.
+
+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 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}
+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.
+
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[], char *envp[])
+{
+    ...
+    /* create two pipes to handle process communication */
+    if ( (retval = pipe(pipein)) ) {
+        WriteMess("input pipe creation error");
+        exit(0);        
+    }
+    if ( (retval = pipe(pipeout)) ) {
+        WriteMess("output pipe creation error");
+        exit(0);        
+    }    
+    /* 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 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}.}
+  \label{fig:ipc_barcode_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
+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-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
+  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
+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 
+
+
+
+
+\subsection{Le funzioni \func{popen} e \func{pclose}}
+\label{sec:ipc_popen}
+
+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 è:
+
+
+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.
+
+
+
 
 
 
@@ -138,7 +282,7 @@ di manipolazione dei file descriptor, come \func{dup} e \func{dup2}, viste in
 \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 procesi con un
+\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
 sul filesystem, e che i processi possono usare per le comunicazioni senza
@@ -152,7 +296,7 @@ dovere per forza essere in relazione diretta.
 
 Per ovviare ai vari limiti dei meccanismo tradizionale di comunicazione fra
 processi visto in \secref{sec:ipc_unix}, nello sviluppo di System V vennero
-introdotti una serie di nuovi oggetti e relative interdacce che garantissero
+introdotti una serie di nuovi oggetti e relative interfacce che garantissero
 una maggiore flessibilità; in questa sezione esamineremo quello che viene
 ormai chiamato il \textit{System V Inter-Process Comunication System}, più
 comunemente noto come \textit{SystemV IPC}.