X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=0b7818c00a9e8ae83a62f18c426ce5f689db6452;hp=21fae712f9ee9894e9c5061670b5b847cd8c4cbc;hb=a29d9eebcd859ca662351848cc856e69f50c3ece;hpb=1f3175061ada629be8bf1a8aa819ed0ed5f9cd3f diff --git a/ipc.tex b/ipc.tex index 21fae71..0b7818c 100644 --- 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