21fae712f9ee9894e9c5061670b5b847cd8c4cbc
[gapil.git] / ipc.tex
1 f\chapter{La comunicazione fra processi}
2 \label{cha:IPC}
3
4
5 Uno degli aspetti fondamentali della programmazione in un sistema unix-like è
6 la comunicazione fra processi. In questo capitolo affronteremo solo i
7 meccanismi più elementari che permettono di mettere in comunicazione processi
8 diversi, come quelli tradizionali che coinvolgono \textit{pipe} e
9 \textit{fifo} e i meccanismi di intercomunicazione di System V.
10
11 Tralasceremo invece tutte le problematiche relative alla comunicazione
12 attraverso la rete (e le relative interfacce) che saranno affrontate in
13 dettaglio in un secondo tempo.  Non affronteremo invece meccanismi più
14 complessi ed evoluti come le RPC (\textit{Remote Procedure Calls}) e CORBA
15 (\textit{Common Object Request Brocker Architecture}) che in genere sono
16 implementati con un ulteriore livello sopra i meccanismi elementari.
17
18
19
20 \section{La comunicazione fra processi tradizionale}
21 \label{sec:ipc_unix}
22
23 Il primo meccanismo di comunicazione fra processi usato dai sistemi unix-like,
24 e quello che viene correntemente usato di più, è quello delle \textit{pipe},
25 che sono una delle caratteristiche peculiari del sistema, in particolar modo
26 dell'interfaccia a linea di comando. In questa sezione descriveremo le sue
27 basi, le funzioni che ne gestiscono l'uso e le varie forme in cui si è
28 evoluto.
29
30
31 \subsection{Le \textit{pipe} standard}
32 \label{sec:ipc_pipes}
33
34 Le \textit{pipe} nascono sostanzialmente con Unix, e sono il primo, e tuttora
35 uno dei più usati, meccanismi di comunicazione fra processi. Si tratta in
36 sostanza di uno speciale tipo di file descriptor, più precisamente una coppia
37 di file descriptor,\footnote{si tenga presente che le pipe sono oggetti creati
38   dal kernel e non risiedono su disco.}  su cui da una parte si scrive e da
39 un'altra si legge. Si viene così a costituire un canale di comunicazione
40 tramite i due file descriptor, nella forma di un \textsl{tubo} (da cui il
41 nome) in cui in genere un processo immette dati che poi arriveranno ad un
42 altro.
43
44 La funzione che permette di creare una pipe è appunto \func{pipe}; il suo
45 prototipo è:
46 \begin{prototype}{unistd.h}
47 {int pipe(int filedes[2])} 
48   
49 Crea una coppia di file descriptor associati ad una pipe.
50   
51   \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
52     errore, nel qual caso \var{errno} potrà assumere i valori \macro{EMFILE},
53     \macro{ENFILE} e \macro{EFAULT}.}
54 \end{prototype}
55
56 La funzione restituisce una coppia di file descriptor nell'array
57 \param{filedes}; il primo aperto in lettura ed il secondo in scrittura. Il
58 concetto di funzionamento di una pipe è relativamente semplice, quello che si
59 scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale
60 nel file descriptor aperto in lettura, da cui può essere riletto.
61
62 I file descriptor infatti non sono connessi a nessun file reale, ma ad un
63 buffer nel kernel, la cui dimensione è specificata dalla costante
64 \macro{PIPE\_BUF}, (vedi \secref{sec:sys_file_limits}); lo schema di
65 funzionamento di una pipe è illustrato in \figref{fig:ipc_pipe_singular}, in
66 cui sono illustrati i due capi della pipe, associati a ciascun file
67 descriptor, con le frecce che indicano la direzione del flusso dei dati
68 attraverso la pipe.
69
70 \begin{figure}[htb]
71   \centering
72   \includegraphics[height=5cm]{img/pipe}
73   \caption{Schema della struttura di una pipe.}
74   \label{fig:ipc_pipe_singular}
75 \end{figure}
76
77 Chiaramente creare una pipe all'interno di un processo non serve a niente; se
78 però ricordiamo quanto esposto in \secref{sec:file_sharing} riguardo al
79 comportamento dei file descriptor nei processi figli, è immediato capire come
80 una pipe possa diventare un meccanismo di intercomunicazione. Un processo
81 figlio infatti condivide gli stessi file descriptor del padre, compresi quelli
82 associati ad una pipe (secondo la situazione illustrata in
83 \figref{fig:ipc_pipe_fork}). In questo modo se uno dei processi scrive su un
84 capo della pipe, l'altro può leggere.
85
86 \begin{figure}[htb]
87   \centering
88   \includegraphics[height=5cm]{img/pipefork}
89   \caption{Schema dell'uso di una pipe come mezzo di comunicazione fra
90   processo attraverso una \func{fork}.}
91   \label{fig:ipc_pipe_fork}
92 \end{figure}
93
94 Tutto ciò ci mostra come sia immediato realizzare un meccanismo di
95 comunicazione fra processi attraverso una pipe, utilizzando le ordinarie
96 proprietà dei file, ma ci mostra anche qual'è il principale\footnote{Stevens
97   riporta in APUE come limite anche il fatto che la comunicazione è
98   unidirezionale, in realtà questo è un limite facilmente risolvibile usando
99   una coppia di pipe.} limite nell'uso delle pipe. È necessario infatti che i
100 processi possano condividere i file descriptor della pipe, e per questo essi
101 devono comunque derivare da uno stesso processo padre che ha aperto la pipe,
102 o, più comunemente, essere nella relazione padre/figlio.
103
104
105
106 \subsection{Un esempio dell'uso delle pipe}
107 \label{sec:ipc_pipe_use}
108
109 Per capire meglio il funzionamento di una pipe faremo un esempio di quello che
110 è il loro uso più comune, analogo a quello effettuato della shell, e che
111 consiste nell'inviare l'output di un processo (lo standard output) sull'input
112 di un'altro. Realizzaremo il programma nella forma di un
113 \textit{cgi-bin}\footnote{breve descrizione, da fare, di cosa è un cgi-bin.}
114 per apache, che genera una immagine JPEG di un codice a barre, specificato
115 come parametro di input.
116
117 Un programma che deve essere eseguito come \textit{cgi-bin} per apache deve
118 rispondere a delle caratteristiche specifiche, esso infatti non viene lanciato
119 da una shell, ma dallo stesso web server, alla richiesta di una specifica URL
120 che di solito ha la forma:
121 \begin{verbatim}
122 http://www.sito.it/cgi-bin/programma?parametro
123 \end{verbatim}
124 ed il risultato dell'elaborazione deve essere presentato (con una intestazione
125 che ne descrive il mime-type) sullo standard output, in modo che apache possa
126 reinviarlo al browser che ha effettuato la richiesta.
127
128
129 Per fare questo useremo in sequenza i programmi \cmd{barcode} e \cmd{gs}, il
130 primo infatti è in grado di generare immagini postscript di codici a barre
131 corrispondenti ad una qualunque stringa, mentre il secondo serve per poter
132 effettuare la conversione della stessa immagine in formato JPEG.
133
134 Si potrebbe obiettare che sarebbe molto più semplice salvare il risultato
135 intermedio su un file temporaneo. Questo però non tiene conto del fatto che il
136 \textit{cgi-bin} deve poter gestire più richieste in concorrenza, e si avrebbe
137 una evidente race condition in caso di accesso simultaneo a detto
138 file.\footnote{la questione potrebbe essere evitata creando prima dei file
139   temporanei, da comunicare poi ai vari processi, e da cancellare alla fine
140   dell'esecuzione; ma a questo punto avremmo perso tutta la semplicità.} L'uso
141 di una pipe invece permette di risolvere il problema in maniera semplice ed
142 elegante.
143
144 Il programma ci servirà anche come esempio dell'uso di alcune delle funzioni
145 di manipolazione dei file descriptor, come \func{dup} e \func{dup2}, viste in
146 \secref{sec:file_dup}; è attraverso queste funzioni che è possibile dirottare
147 gli stream standard dei processi (che abbiamo visto in
148 \secref{sec:file_std_descr} e \secref{sec:file_std_stream}) sulla pipe. Le
149 sezioni significative del programma è riportato in
150 \figref{fig:ipc_barcode_code}, il codice è disponibile nel file
151 \file{BarCode.c} nella directory dei sorgenti.
152
153
154 \begin{figure}[!htb]
155   \footnotesize \centering
156   \begin{minipage}[c]{15cm}
157     \begin{lstlisting}{}
158 int main(int argc, char *argv[], char *envp[])
159 {
160     ...
161     /* create two pipes to handle process communication */
162     if ( (retval = pipe(pipein)) ) {
163         WriteMess("input pipe creation error");
164         exit(0);        
165     }
166     if ( (retval = pipe(pipeout)) ) {
167         WriteMess("output pipe creation error");
168         exit(0);        
169     }    
170     /* fork child to run barcode program */
171     pid = fork();
172     if (pid == -1) {
173         WriteMess("child creation error");
174         exit(0);        
175     }
176     /* if child */
177     if (pid == 0) {
178         close(pipein[1]);        /* close output side of input pipe */
179         dup2(0, pipein[0]);      /* remap stdin in pipe input */
180         close(pipeout[0]);       /* close input side of output pipe */
181         dup2(1, pipeout[1]);     /* remap stdout in pipe output */
182         execlp("barcode", "barcode", "-E", NULL);
183     } else { 
184         /* first set the pipe */
185         close(pipein[0]);        /* close input side of input pipe */
186         close(pipeout[1]);       /* close output side of output pipe */
187         write(pipein[1], argv[1], strlen(argv[1]));
188         close(pipein[1]);
189         waitpid(pid, NULL, 0);
190         pid = fork();
191         if (pid == -1) {
192             WriteMess("child creation error")
193             exit(0);
194         }
195         if (pid == 0) {
196             /* send mime type */
197             write(0,content, strlen(content));
198             dup2(0, pipeout[0]);
199             execlp("gs", "gs", "-sDEVICE=jpeg", "-sOutputFile=-", "-", NULL);
200         } else {
201             close(pipeout[0]);
202             waitpid(pid, NULL, 0);
203         }
204     }
205     exit(0);
206 }
207     \end{lstlisting}
208   \end{minipage} 
209   \normalsize 
210   \caption{Codice del \textit{cgi-bin} \cmd{BarCode}.}
211   \label{fig:ipc_barcode_code}
212 \end{figure}
213
214
215 Il primo passo (\texttt{\small 4-12}) è quello di creare le due pipe, una per
216 l'input e l'altra per l'output, che servono per la comunicazione con i due
217 programmi che verranno utilizzati, inviando in caso di errore (attraverso una
218 apposita funzione \func{WriteMess}, non riportata in
219 \ref{fig:ipc_barcode_code}, che si incarica di formattare l'output in HTML
220 perché sia interpretabile da un browser) un messaggio invece dell'immagine
221 richiesta.
222
223 Una volta create le pipe il programma può creare (\texttt{\small 13-18}) il
224 primo processo figlio, che si incaricherà (\texttt{\small 19-25}) di eseguire
225 \cmd{barcode}: quest'ultimo funziona ricevendo dallo standard input la stringa
226 da convertire nell'immagine postscript del codice a barre che sarà scritta
227 sullo standard output.  
228
229 Per questo il processo figlio prima chiude (\texttt{\small 21}) il capo aperto
230 in scrittura della prima pipe (che sarà usato dal padre per trasmettergli la
231 stringa da codificare), e poi collega (\texttt{\small 22}) il capo il lettura
232 allo standard input usando \func{dup2}.  Analogamente il capo in lettura della
233 seconda pipe sarà chiuso mentre il capo in scrittura viene collegato allo
234 standard output (\texttt{\small 23-24}.  In questo modo all'esecuzione
235 (\texttt{\small 25}) di \cmd{barcode} quest'ultimo leggerà la stringa da
236 codificare dalla prima pipe e scriverà l'immagine postscript nella seconda.
237
238 Dall'altra parte il processo padre prima chiude (\texttt{\small 28-29}) i due
239 capi inutilizzati delle pipe (input della prima ed output della seconda), poi
240 scrive (\texttt{\small 30}) la stringa da convertire sull'output della prima
241 pipe così che \cmd{barcode} possa riceverla dallo standard input; a questo
242 punto l'uso della prima pipe è finito ed essa può essere definitivamente
243 chiusa (\texttt{\small 31}), si attenderà poi (\texttt{\small 32}) che
244 l'esecuzione di \cmd{barcode} venga completata.
245
246 Alla conclusione della sua esecuzione \cmd{barcode} avrà effettuato inviato
247 l'immagine postscript del codice a barre sul capo in scrittura della seconda
248 pipe; a questo punto 
249
250
251
252
253 \subsection{Le funzioni \func{popen} e \func{pclose}}
254 \label{sec:ipc_popen}
255
256 Come si è visto la modalità più comune di utilizzo di una pipe è quella di
257 utilizzarla per fare da tramite fra output ed input di due programmi invocati
258 in sequenza; per questo motivo lo standard POSIX.2 ha introdotto due funzioni
259 che permettono di sintetizzare queste operazioni comuni in una sola
260 chiamata. La prima di esse si chiama \func{popen} ed il suo prototipo è:
261
262
263 L'esempio in \figref{fig:ipc_barcode_code} per quanto perfettamente
264 funzionante, è piuttosto complesso; inoltre nella pratica sconta un problema
265 di \cmd{gs} che non è in grado\footnote{nella versione GNU Ghostscript 6.53
266   (2002-02-13).} di riconoscere correttamente l'encapsulated postscript, per
267 cui tutte le volte generata una pagina intera, invece che una semplice figura.
268 Se si vuole generare una immagine di dimensioni corrette si deve allora
269 ricorrere ad ulteriore programma, \cmd{epstopsf}, per convertire in PDF il
270 file EPS generato da \cmd{barcode}, che invece viene trattato correttamente.
271
272
273
274
275
276
277 \subsection{Le \textit{pipe} con nome, o \textit{fifo}}
278 \label{sec:ipc_named_pipe}
279
280 Per poter superare il problema delle \textit{pipe}, illustrato in
281 \secref{sec:ipc_pipes}, che ne consente l'uso solo fra processi con un
282 progenitore comune o nella relazione padre/figlio, lo standard POSIX.1
283 definisce dei nuovi oggetti, le \textit{fifo}, che invece possono risiedere
284 sul filesystem, e che i processi possono usare per le comunicazioni senza
285 dovere per forza essere in relazione diretta.
286
287
288
289   
290 \section{La comunicazione fra processi di System V}
291 \label{sec:ipc_sysv}
292
293 Per ovviare ai vari limiti dei meccanismo tradizionale di comunicazione fra
294 processi visto in \secref{sec:ipc_unix}, nello sviluppo di System V vennero
295 introdotti una serie di nuovi oggetti e relative interfacce che garantissero
296 una maggiore flessibilità; in questa sezione esamineremo quello che viene
297 ormai chiamato il \textit{System V Inter-Process Comunication System}, più
298 comunemente noto come \textit{SystemV IPC}.
299  
300
301 \subsection{Code di messaggi}
302 \label{sec:ipc_messque}
303
304 Il primo oggetto introdotto dal \textit{SystemV IPC} è quello delle code di
305 messaggi.
306
307 \subsection{Semafori}
308 \label{sec:ipc_semaph}
309
310 Il secondo oggetto introdotto dal \textit{SystemV IPC} è quello dei semafori.
311
312
313 \subsection{Memoria condivisa}
314 \label{sec:ipc_shar_mem}
315
316 Il terzo oggetto introdotto dal \textit{SystemV IPC} è quello della memoria
317 condivisa.
318
319 %%% Local Variables: 
320 %%% mode: latex
321 %%% TeX-master: "gapil"
322 %%% End: