X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=3c30111cebf747b7316715bdcc672a4e373b441c;hp=40c9fadd4c20f23f608497e443a65a2972107868;hb=f554a11afa7c50c2b0267e890fb7581b6605384d;hpb=2e715e70ba0df8224ec1bf118ba34a73a21df5c5 diff --git a/ipc.tex b/ipc.tex index 40c9fad..3c30111 100644 --- a/ipc.tex +++ b/ipc.tex @@ -217,7 +217,8 @@ int main(int argc, char *argv[], char *envp[]) \end{lstlisting} \end{minipage} \normalsize - \caption{Codice del \textit{CGI} \cmd{BarCodePage}.} + \caption{Sezione principale del codice del \textit{CGI} + \file{BarCodePage.c}.} \label{fig:ipc_barcode_code} \end{figure} @@ -240,10 +241,13 @@ 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}). +\func{dup2}. Si ricordi che invocando \func{dup2} il secondo file, qualora +risulti aperto, viene, come nel caso corrente, chiuso prima di effettuare la +duplicazione. Allo stesso modo, 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 @@ -254,9 +258,9 @@ 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. +l'uso della prima pipe da parte del padre è 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 @@ -276,15 +280,15 @@ 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 +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. +(\texttt{\small 45}); a questo punto può (\texttt{\small 46}) uscire. 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}} @@ -339,64 +343,63 @@ attendendo la terminazione del processo ad essa associato. (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; +Per illustrare l'uso di queste due funzioni riprendiamo il problema +precedente: il programma mostrato in \figref{fig:ipc_barcode_code} per quanto +funzionante, è (volutamente) codificato in maniera piuttosto complessa, 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. +riconoscere correttamente l'encapsulated postscript, per cui deve essere usato +il postscript e tutte le volte viene generata una pagina intera, invece che +una immagine delle dimensioni corrispondenti al codice a barre. + +Se si vuole generare una immagine di dimensioni appropriate si deve usare un +approccio diverso. Una possibilità sarebbe quella di ricorrere ad ulteriore +programma, \cmd{epstopsf}, per convertire in PDF un file EPS (che può essere +generato da \cmd{barcode} utilizzando lo switch \cmd{-E}). 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 +\func{lseek} sul file da convertire; se si esegue \cmd{gs} su un file normale +non ci sono problemi, ma una pipe però è rigidamente sequenziale, ed il +tentativo di eseguire detta operazione su una pipe comporta l'immediato +fallimento con un errore di \macro{ESPIPE}. Questo ci dice che in generale la +concatenazione di vari programmi funzionerà soltanto quando tutti prevedono +una lettura sequenziale del loro input. + +Per questo motivo si è dovuto utilizzare 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. +\cmd{pnmmargin}) che può essere infine trasformata in PNG (con \cmd{pnm2png}). -In questo caso però occorre eseguire sequenza ben quattro comandi diversi, +In questo caso però occorre eseguire in 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. - +risultato finale sullo standard output; un caso classico di utilizzazione +delle pipe, in cui l'uso di \func{popen} e \func{pclose} permette di +semplificare notevolmente la stesura del codice. -Dato che questo caso ciascun processo deve scrivere il suo output sullo +Nel nostro caso, dato che 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. +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. \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; @@ -425,42 +428,41 @@ int main(int argc, char *argv[], char *envp[]) } 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("
\n"); } -} - \end{lstlisting} \end{minipage} \normalsize - \caption{Codice del \textit{cgi-bin} \cmd{BarCode2}.} - \label{fig:ipc_barcode2_code} + \caption{Codice completo del \textit{CGI} \file{BarCode.c}.} + \label{fig:ipc_barcode_code} \end{figure} -Nel nostro caso il primo passo (\texttt{\small 12}) è scrivere il mime-type +Nel nostro caso il primo passo (\texttt{\small 14}) è 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}. +provvedere alla redirezione. + +Dato che i vari programmi devono essere lanciati in successione, si è +approntato un ciclo (\texttt{\small 15--19}) che esegue le operazioni in +sequenza: prima crea una pipe (\texttt{\small 17}) per la scrittura eseguendo +il programma con \func{popen}, in modo che essa sia collegata allo standard +input, e poi redirige (\texttt{\small 18}) lo standard output su detta pipe. + +In questo modo il primo processo ad essere invocato (che è l'ultimo della +catena) scriverà ancora sullo standard output del processo padre, ma i +successivi, a causa di questa redirezione, scriveranno sulla pipe associata +allo standard input del processo invocato nel ciclo precedente. + +Alla fine tutto quello che resta da fare è lanciare (\texttt{\small 21}) il +primo processo della catena, che nel caso è \cmd{barcode}, e scrivere +(\texttt{\small 23}) la stringa del codice a barre sulla pipe, che è collegata +al suo standard input, infine si può eseguire (\texttt{\small 24--27}) un +ciclo, che chiuda, nell'ordine inverso rispetto a quello in cui le si sono +create, tutte le pipe create con \func{pclose}. \subsection{Le \textit{pipe} con nome, o \textit{fifo}}