Sistemati gli indici.
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 3c30111cebf747b7316715bdcc672a4e373b441c..bdbdf2c13d9068e85617b49f2ff16cc321cf416e 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -101,6 +101,23 @@ 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.
 
+A differenza di quanto avviene con i file normali la lettura da una pipe può
+essere bloccante (qualora non siano presenti dati), inoltre se si legge da una
+pipe il cui capo in scrittura è stato chiuso, si avrà la ricezione di un EOF
+(vale a dire che la funzione \func{read} ritornerà restituendo 0).  Se invece
+si esegue una scrittura su una pipe il cui capo in lettura non è aperto il
+processo riceverà il segnale \macro{EPIPE}, e la funzione di scrittura
+restituirà un errore di \macro{EPIPE} (al ritorno del manipolatore, o qualora
+il segnale sia ignorato o bloccato).
+
+La dimensione del buffer della pipe (\macro{PIPE\_BUF}) ci dà inoltre un'altra
+importante informazione riguardo il comportamento delle operazioni di lettura
+e scrittura su di una pipe; esse infatti sono atomiche fintanto che la
+quantità di dati da scrivere non supera questa dimensione. Qualora ad esempio
+si effettui una scrittura di una quantità di dati superiore l'operazione verrà
+effettuata in più riprese, consentendo l'intromissione di scritture effettuate
+da altri processi.
+
 
 \subsection{Un esempio dell'uso delle pipe}
 \label{sec:ipc_pipe_use}
@@ -148,7 +165,7 @@ intermedio su un file temporaneo. Questo per
 \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{il problema potrebbe essere superato determinando in anticipo
-  un nome appropiato per il file temporaneo, che verrebbe utilizzato dai vari
+  un nome appropriato per il file temporaneo, che verrebbe utilizzato dai vari
   sotto-processi, e cancellato alla fine della loro esecuzione; ma a questo le
   cose non sarebbero più tanto semplici.}  L'uso di una pipe invece permette
 di risolvere il problema in maniera semplice ed elegante.
@@ -158,8 +175,8 @@ duplicazione dei file descriptor che abbiamo trattato in
 \secref{sec:file_dup}, in particolare di \func{dup2}. È attraverso queste
 funzioni infatti 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. In \figref{fig:ipc_barcode_code}
-abbiamo riportato il corpo del programm, il cui codice completo è disponibile
+\secref{sec:file_std_stream}) sulla pipe. In \figref{fig:ipc_barcodepage_code}
+abbiamo riportato il corpo del programma, il cui codice completo è disponibile
 nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti.
 
 
@@ -219,7 +236,7 @@ int main(int argc, char *argv[], char *envp[])
   \normalsize 
   \caption{Sezione principale del codice del \textit{CGI} 
     \file{BarCodePage.c}.}
-  \label{fig:ipc_barcode_code}
+  \label{fig:ipc_barcodepage_code}
 \end{figure}
 
 La prima operazione del programma (\texttt{\small 4--12}) è quella di creare
@@ -227,10 +244,10 @@ le due pipe che serviranno per la comunicazione fra i due comandi 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
-  \secref{fig:ipc_barcode_code}; essa si incarica semplicemente di formattare
-  l'uscita alla maniera dei CGI, aggiungendo l'opportuno \textit{mime type}, e
-  formattando il messaggio in HTML, in modo che quest'ultimo possa essere
-  visualizzato correttamente da un browser.}
+  \secref{fig:ipc_barcodepage_code}; essa si incarica semplicemente di
+  formattare l'uscita alla maniera dei CGI, aggiungendo l'opportuno
+  \textit{mime type}, e formattando il messaggio in HTML, in modo che
+  quest'ultimo possa essere visualizzato correttamente 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
@@ -285,7 +302,7 @@ capo in scrittura della seconda pipe, e attende la conclusione del figlio
 (\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
+standard 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.
@@ -332,7 +349,7 @@ 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}
+Chiude il file \param{stream}, restituito da una precedente \func{popen}
 attendendo la terminazione del processo ad essa associato.
   
 \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
@@ -344,8 +361,8 @@ attendendo la terminazione del processo ad essa associato.
 \func{popen}.
 
 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,
+precedente: il programma mostrato in \figref{fig:ipc_barcodepage_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 deve essere usato
@@ -380,19 +397,19 @@ dimensioni corrette attraverso vari programmi di manipolazione (\cmd{pnmcrop},
 
 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; un caso classico di utilizzazione
+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.
 
 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
+\figref{fig:ipc_barcode_code}.  Come si può notare l'ordine di invocazione dei
+programmi è l'inverso di quello in cui ci si aspetta che vengano
+effettivamente eseguiti. Questo non comporta nessun problema dato che 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
+risultato dell'elaborazione del precedente, benchè quest'ultimo venga
 invocato dopo.
 
 \begin{figure}[!htb]
@@ -427,12 +444,6 @@ int main(int argc, char *argv[], char *envp[])
         pclose((pipe[i]));
     }
     exit(0);
-}
-void WriteMess(char *mess)
-{
-    printf("Content-type: text/html\n\n");
-    perror(mess);
-    printf("<br>\n");
 }
     \end{lstlisting}
   \end{minipage} 
@@ -472,61 +483,80 @@ Come accennato in \secref{sec:ipc_pipes} il problema delle \textit{pipe} 
 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.
-
-Utilizzando una fifo tutti i dati passeranno attraverso un apposito buffer nel
-kernel, senza transitare dal filesystem, l'inode serve solo a fornire un punto
-d'appoggio per i vari processi che permetta loro di accedere alla stessa
-fifo.  
-
-
-
-
-Abbiamo già visto in \secref{sec:file_mknod} le modalità che permettono di
-creare una fifo, attraverso le funzioni \func{mknod} e \func{mkfifo}; per
-utilizzarle un processo non avrà che da aprire il relativo file in lettura o
-scrittura (a seconda della direzione che si vuole dare ai dati).
-
-che invece possono risiedere
-sul filesystem, e che i processi possono usare per le comunicazioni senza
-dovere per forza essere in relazione diretta.
-
-
+caratteristiche delle pipe, ma che invece di essere strutture interne del
+kernel, visibili solo attraverso un file descriptor, sono accessibili
+attraverso un inode che risiede sul filesystem, così che i processi le possono
+usare senza dovere per forza essere in una relazione di \textsl{parentela}.
+
+Utilizzando una \textit{fifo} tutti i dati passeranno, come per le pipe,
+attraverso un apposito buffer nel kernel, senza transitare dal filesystem;
+l'inode allocato sul filesystem serve infatti solo a fornire un punto di
+riferimento per i processi, che permetta loro di accedere alla stessa fifo; il
+comportamento delle funzioni di lettura e scrittura è identico a quello
+illustrato per le pipe in \secref{sec:ipc_pipes}.
+
+Abbiamo già visto in \secref{sec:file_mknod} le funzioni \func{mknod} e
+\func{mkfifo} che permettono di creare una fifo; per utilizzarne una un
+processo non avrà che da aprire il relativo file speciale o in lettura o
+scrittura; nel primo caso sarà collegato al capo di uscita della fifo, e dovrà
+leggere, nel secondo al capo di ingresso, e dovrà scrivere.
+
+Il kernel crea una singola pipe per ciascuna fifo che sia stata aperta, che può
+essere acceduta contemporaneamente da più processi, sia in lettura che in
+scrittura. Dato che per funzionare deve essere aperta in entrambe le
+direzioni, per una fifo di norma la funzione \func{open} si blocca se viene
+eseguita quando l'altro capo non è aperto.
+
+Le fifo però possono essere anche aperte in modalità \textsl{non-bloccante},
+nel qual caso l'apertura del capo in lettura avrà successo solo quando anche
+l'altro capo è aperto, mentre l'apertura del capo in scrittura restituirà
+l'errore di \macro{ENXIO} fintanto che non verrà aperto il capo in lettura.
+
+In Linux\footnote{lo standard POSIX lascia indefinito questo comportamento.} è
+possibile aprire le fifo anche in lettura/scrittura, operazione che avrà
+sempre successo immediato qualunque sia la modalità di apertura (bloccante e
+non bloccante); questo può essere utilizzato per aprire comunque una fifo in
+scrittura anche se non ci sono ancora processi il lettura; è possibile anche
+usare la fifo all'interno di un solo processo, nel qual caso però occorre
+stare molto attenti alla possibili deadlock.\footnote{se si cerca di leggere
+  da una fifo che non contiene dati si avrà un deadlock immediato, dato che il
+  processo si blocca e non potrà quindi mai eseguire le funzioni di
+  scrittura.}
 
 
-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}.
+Benché le pipe (e le fifo) siano ancora ampiamente usate, esse presentano
+numerosi limiti, il principale dei quali è che il meccanismo di comunicazione
+è rigidamente sequenziale; una situazione in cui un processo scrive qualcosa
+che molti altri devono poter leggere non può essere implementata con una pipe.
+
+Per superarne i vari limiti, nello sviluppo di System V vennero introdotti una
+serie di nuovi oggetti di comunicazione e relative interfacce id
+programmazione che garantissero una maggiore flessibilità; in questa sezione
+esamineremo quello che viene ormai chiamato il \textsl{Sistema di
+  comunicazione inter-processo} di System V , più comunemente noto come
+\textit{System V IPC (Inter-Process Comunication)}.
  
 
 \subsection{Code di messaggi}
 \label{sec:ipc_messque}
 
-Il primo oggetto introdotto dal \textit{SystemV IPC} è quello delle code di
+Il primo oggetto introdotto dal \textit{System V IPC} è quello delle code di
 messaggi.
 
 \subsection{Semafori}
 \label{sec:ipc_semaph}
 
-Il secondo oggetto introdotto dal \textit{SystemV IPC} è quello dei semafori.
+Il secondo oggetto introdotto dal \textit{System V IPC} è quello dei semafori.
 
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_shar_mem}
 
-Il terzo oggetto introdotto dal \textit{SystemV IPC} è quello della memoria
+Il terzo oggetto introdotto dal \textit{System V IPC} è quello della memoria
 condivisa.
 
 %%% Local Variables: