-f\chapter{La comunicazione fra processi}
+\chapter{La comunicazione fra processi}
\label{cha:IPC}
è 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
\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
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{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