\chapter{La comunicazione fra processi}
\label{cha:IPC}


Uno degli aspetti fondamentali della programmazione in un sistema unix-like è
la comunicazione fra processi. In questo capitolo affronteremo solo i
meccanismi più elementari che permettono di mettere in comunicazione processi
diversi, come quelli tradizionali che coinvolgono \textit{pipe} e
\textit{fifo} e i meccanismi di intercomunicazione di System V.

Tralasceremo invece tutte le problematiche relative alla comunicazione
attraverso la rete (e le relative interfacce) che saranno affrontate in
dettaglio in un secondo tempo.  Non affronteremo invece meccanismi più
complessi ed evoluti come le RPC (\textit{Remote Procedure Calls}) e CORBA
(\textit{Common Object Request Brocker Architecture}) che in genere sono
implementati con un ulteriore livello sopra i meccanismi elementari.



\section{La comunicazione fra processi tradizionale}
\label{sec:ipc_unix}

Il primo meccanismo di comunicazione fra processi usato dai sistemi unix-like,
e quello che viene correntemente usato di più, è quello delle \textit{pipe},
che sono una delle caratteristiche peculiari del sistema, in particolar modo
dell'interfaccia a linea di comando. In questa sezione descriveremo le sue
basi, le funzioni che ne gestiscono l'uso e le varie forme in cui si è
evoluto.


\subsection{Le \textit{pipe} standard}
\label{sec:ipc_pipes}

Le \textit{pipe} nascono sostanzialmente con Unix, e sono il primo, e tuttora
uno dei più usati, meccanismi di comunicazione fra processi. Si tratta in
sostanza di uno speciale tipo di file descriptor, più precisamente una coppia
di file descriptor,\footnote{si tenga presente che le pipe sono oggetti creati
  dal kernel e non risiedono su disco.}  su cui da una parte si scrive e da
un'altra si legge. Si viene così a costituire un canale di comunicazione
tramite i due file descriptor, nella forma di un \textsl{tubo} (da cui il
nome) in cui in genere un processo immette dati che poi arriveranno ad un
altro.

La funzione che permette di creare una pipe è appunto \func{pipe}; il suo
prototipo è:
\begin{prototype}{unistd.h}
{int pipe(int filedes[2])} 
  
Crea una coppia di file descriptor associati ad una pipe.
  
  \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
    errore, nel qual caso \var{errno} potrà assumere i valori \macro{EMFILE},
    \macro{ENFILE} e \macro{EFAULT}.}
\end{prototype}

La funzione restituisce una coppia di file descriptor nell'array
\param{filedes}; il primo aperto in lettura ed il secondo in scrittura. Il
concetto di funzionamento di una pipe è relativamente semplice, quello che si
scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale
nel file descriptor aperto in lettura, da cui può essere riletto.

I file descriptor infatti non sono connessi a nessun file reale, ma ad un
buffer nel kernel, la cui dimensione è specificata dalla costante
\macro{PIPE\_BUF}, (vedi \secref{sec:sys_file_limits}); lo schema di
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
attraverso la pipe.

\begin{figure}[htb]
  \centering
  \includegraphics[height=5cm]{img/pipe}
  \caption{Schema della struttura di una pipe.}
  \label{fig:ipc_pipe_singular}
\end{figure}

Chiaramente creare una pipe all'interno di un processo non serve a niente; se
però ricordiamo quanto esposto in \secref{sec:file_sharing} riguardo al
comportamento dei file descriptor nei processi figli, è immediato capire come
una pipe possa diventare un meccanismo di intercomunicazione. Un processo
figlio infatti condivide gli stessi file descriptor del padre, compresi quelli
associati ad una pipe (secondo la situazione illustrata in
\figref{fig:ipc_pipe_fork}). In questo modo se uno dei processi scrive su un
capo della pipe, l'altro può leggere.

\begin{figure}[htb]
  \centering
  \includegraphics[height=5cm]{img/pipefork}
  \caption{Schema dell'uso di una pipe come mezzo di comunicazione fra
  processo attraverso una \func{fork}.}
  \label{fig:ipc_pipe_fork}
\end{figure}

Tutto ciò ci mostra come sia immediato realizzare un meccanismo di
comunicazione fra processi attraverso una pipe, utilizzando le ordinarie
proprietà dei file, ma ci mostra anche qual'è il principale\footnote{Stevens
  in \cite{APUE} riporta come limite anche il fatto che la comunicazione è
  unidirezionale, in realtà questo è un limite facilmente superabile usando
  una coppia di pipe.} limite nell'uso delle pipe. È necessario infatti che i
processi possano condividere i file descriptor della pipe, e per questo essi
devono comunque derivare da uno stesso processo padre che ha aperto la pipe,
o, più comunemente, essere nella relazione padre/figlio.



\subsection{Un esempio dell'uso delle pipe}
\label{sec:ipc_pipe_use}

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}\footnote{NdA, inserire una breve descrizione di cosa è un cgi.}
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} 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} 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}; è 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
  20}) 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 21}) il capo in lettura della pipe 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}).  

In questo modo all'esecuzione (\texttt{\small 25}) di \cmd{barcode} (cui si
passa in \var{size} la dimensione per l'immagine) quest'ultimo leggerà la
stringa da codificare che gli viene inviata dal padre dalla prima pipe e
scriverà l'immagine postscript del codice a barre sulla seconda.

Dall'altra parte il processo padre prima chiude (\texttt{\small 26}) il capo
inutilizzato della prima pipe (quello in input), 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.

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 si può eseguire la seconda conversione, da PS a JPEG,
usando il programma \cmd{gs}. Per questo si crea (\texttt{\small 30--34}) un
secondo processo figlio, che poi (\texttt{\small 35--42}) eseguirà questo
programma leggendo l'immagine postscript creata da \cmd{barcode} sullo
standard input per convertirla in JPEG.

Per fare tutto ciò il secondo figlio anzitutto chiude (\texttt{\small 37}) il
capo in scrittura della seconda pipe, e collega (\texttt{\small 38}) il capo
in lettura allo standard input. Per poter formattare l'output del programma in
maniera utilizzabile da un browser, si provvede anche \texttt{\small 40}) alla
scrittura dell'apposita stringa di mime-type in testa allo standard output. A
questo punto si può invocare \texttt{\small 41}) il programma \cmd{gs},
provvedendo gli appositi switch che consentono di leggere il file da
convertire dallo standard input, ed inviare la conversione sullo standard
output.

Per concludere 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}), per poi uscire \texttt{\small 46}). Si tenga conto che,
l'operazione di chiudere il capo in scrittura della seconda pipe è necessaria,
infatti non chiudendola \cmd{gs}, che legge il suo stardard input da detta
pipe, resterebbe bloccato in attesa di ulteriore input (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}}
\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. La prima di esse si chiama
\func{popen} ed il suo prototipo è:
\begin{prototype}{stdio.h}
{FILE *popen(const char *command, const char *type)}

Esegue il programma \param{command}, di cui, a seconda di \param{type},
restituisce, lo standard input o lo standard output nella pipe collegata allo
stream restituito come valore di ritorno.
  
\bodydesc{La funzione restituisce l'indirizzo dello stream associato alla pipe
  in caso di successo e \macro{NULL} per un errore, nel qual caso \var{errno}
  potrà assumere i valori relativi alle sottostanti invocazioni di \func{pipe}
  e \func{fork} o \macro{EINVAL} se \param{type} non è valido.}
\end{prototype}
\noindent e serve per semplificare l'uso di \func{pipe}. 

La funzione crea una pipe, esegue una \func{fork}, ed invoca il programma
\param{command} attraverso la shell (in sostanza esegue \file{/bin/sh} con il
flag \code{-c}); l'argomento \param{type} deve essere una stringa \verb|"w"| o
\verb|"r"|, per indicare se la pipe sarà collegata allo standard input o allo
standard output del comando invocato.

La funzione restituisce il puntatore allo stream associato alla pipe creata,
che sarà aperto in sola lettura (e quindi associato allo standard output del
programma indicato) in caso si sia indicato \code{"r"}, o in sola scrittura (e
quindi associato allo standard input) in caso di \code{"w"}.

Lo stream restituito da \func{popen} è identico a tutti gli effetti ai file
standard visti in \secref{cha:files_std_interface}, e viene sempre aperto in
modalità \textit{fully-buffered} (vedi \secref{sec:file_buffering}); l'unica
differenza è che deve essere chiuso dalla seconda delle due funzioni,
\func{pclose}, il cui prototipo è:
\begin{prototype}{stdio.h}
{int pclose(FILE *stream)}

Chiude il file \param{stream}, restituito da una prededente \func{popen}
attendendo la terminazione del processo ad essa associato.
  
\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
  errore; nel quel caso il valore di \func{errno} deriva dalle sottostanti
  chiamate.}
\end{prototype}
\noindent che si incarica anche di attendere la conclusione del processo
creato dalla precedente \func{popen}.

Per illustrare l'uso di queste due funzioni riprendiamo l'esempio in
\figref{fig:ipc_barcode_code}: esso per quanto 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}. Utilizzando un file in PDF invece, \cmd{gs} esegue
la conversione rispettando le dimensioni originarie del codice a barre.





\subsection{Le \textit{pipe} con nome, o \textit{fifo}}
\label{sec:ipc_named_pipe}

Come accennato in \secref{sec:ipc_pipes} il problema delle \textit{pipe} è che
esse possono essere utilizzate solo da processi con un progenitore comune o
nella relazione padre/figlio; per superare questo problema lo standard POSIX.1
ha definito dei nuovi oggetti, le \textit{fifo}, che hanno le stesse
caratteristiche delle pipe, ma invece che essere struttura interne del kernel
visibili solo attraverso un file descriptor comune, possono essere viste
attraverso un inode che risiede sul filesystem.


Abbiamo già accennato in \secref{sec:file_mknod}

che invece possono risiedere
sul filesystem, e che i processi possono usare per le comunicazioni senza
dovere per forza essere in relazione diretta.




Per poter superare il problema delle \textit{pipe}, illustrato in
\secref{sec:ipc_pipes}, che ne consente l'uso solo fra processi con un
progenitore comune o nella relazione padre/figlio,
  
\section{La comunicazione fra processi di System V}
\label{sec:ipc_sysv}

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 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}.
 

\subsection{Code di messaggi}
\label{sec:ipc_messque}

Il primo oggetto introdotto dal \textit{SystemV IPC} è quello delle code di
messaggi.

\subsection{Semafori}
\label{sec:ipc_semaph}

Il secondo oggetto introdotto dal \textit{SystemV IPC} è quello dei semafori.


\subsection{Memoria condivisa}
\label{sec:ipc_shar_mem}

Il terzo oggetto introdotto dal \textit{SystemV IPC} è quello della memoria
condivisa.

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "gapil"
%%% End: 
