Avanti sulle message queues
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 03bc5e790755d3525bed19df604eb9b2e8cc9c4e..b5e7981f69c17cfbb835dccc66e431d374ec811c 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -10,22 +10,20 @@ diversi, come quelli tradizionali che coinvolgono \textit{pipe} e
 
 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ù
+dettaglio in un secondo tempo.  Non affronteremo neanche 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.
+Il primo meccanismo di comunicazione fra processi introdotto nei sistemi Unix,
+è quello delle cosiddette \textit{pipe}; esse costituiscono 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}
@@ -33,39 +31,36 @@ evoluto.
 
 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 è:
+sostanza di una una coppia di file descriptor\footnote{si tenga presente che
+  le pipe sono oggetti creati dal kernel e non risiedono su disco.} connessi
+fra di loro in modo che se quanto scrive su di uno si può rileggere
+dall'altro. Si viene così a costituire un canale di comunicazione tramite i
+due file descriptor, nella forma di un \textsl{tubo} (da cui il nome)
+attraverso cui fluiscono i dati.
+
+La funzione che permette di creare questa speciale coppia di file descriptor
+associati ad una \textit{pipe} è appunto \func{pipe}, ed il suo prototipo è:
 \begin{prototype}{unistd.h}
 {int pipe(int filedes[2])} 
   
-Crea una coppia di file descriptor associati ad una pipe.
+Crea una coppia di file descriptor associati ad una \textit{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
+La funzione restituisce la coppia di file descriptor nel vettore
+\param{filedes}; il primo è aperto in lettura ed il secondo in scrittura. Come
+accennato concetto di funzionamento di una pipe è 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.
+nel file descriptor aperto in lettura. 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.
 
 \begin{figure}[htb]
   \centering
@@ -74,12 +69,12 @@ attraverso la 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
+Chiaramente creare una pipe all'interno di un singolo 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.
 
@@ -92,16 +87,17 @@ capo della pipe, l'altro pu
 \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
+comunicazione fra processi attraverso una pipe, utilizzando le proprietà
+ordinarie 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
+  unidirezionale, ma 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.
+devono comunque essere \textsl{parenti} (dall'inglese \textit{siblings}), cioè
+o derivare da uno stesso processo padre in cui è avvenuta la creazione della
+pipe, o, più comunemente, essere nella relazione padre/figlio.
 
-A differenza di quanto avviene con i file normali la lettura da una pipe può
+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
@@ -122,14 +118,14 @@ da altri processi.
 \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
+Per capire meglio il funzionamento delle 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. Realizzeremo il programma nella forma di un
-\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un programma
-  che permette la creazione dinamica di un oggetto da inserire all'interno di
-  una pagina HTML.}  per apache, che genera una immagine JPEG di un codice a
-barre, specificato come parametro di input.
+di un'altro. Realizzeremo il programma di esempio nella forma di un
+\textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un
+  programma che permette la creazione dinamica di un oggetto da inserire
+  all'interno di una pagina HTML.}  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} deve rispondere a
 delle caratteristiche specifiche, esso infatti non viene lanciato da una
@@ -143,13 +139,13 @@ che ne descrive il mime-type) sullo standard output, in modo che il web-server
 possa reinviarlo al browser che ha effettuato la richiesta, che in questo modo
 è in grado di visualizzarlo opportunamente.
 
-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. Usando una
-pipe potremo inviare l'output del primo sull'input del secondo, secondo lo
-schema mostrato in \figref{fig:ipc_pipe_use}, in cui la direzione del flusso
-dei dati è data dalle frecce continue.
+Per realizzare quanto voluto 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. Usando una pipe potremo inviare l'output del primo sull'input del
+secondo, secondo lo schema mostrato in \figref{fig:ipc_pipe_use}, in cui la
+direzione del flusso dei dati è data dalle frecce continue.
 
 \begin{figure}[htb]
   \centering
@@ -188,7 +184,7 @@ nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti.
 int main(int argc, char *argv[], char *envp[])
 {
     ...
-    /* create two pipes to handle process communication */
+    /* create two pipes, pipein and pipeout, to handle communication */
     if ( (retval = pipe(pipein)) ) {
         WriteMess("input pipe creation error");
         exit(0);        
@@ -208,14 +204,14 @@ int main(int argc, char *argv[], char *envp[])
         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);
+        execlp("barcode", "barcode", size, 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 */
+    if ( (pid = fork()) == -1) {
         WriteMess("child creation error");
         exit(0);
     }
@@ -244,7 +240,7 @@ La prima operazione del programma (\texttt{\small 4--12}) 
 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
+richiesta.\footnote{la funzione \func{WriteMess} non è riportata in
   \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
@@ -375,26 +371,27 @@ approccio diverso. Una possibilit
 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; 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 (con \cmd{pnm2png}).
+originarie del codice a barre e produce un JPEG di dimensioni corrette.
+
+Questo approccio però non funziona, per via di una delle caratteristiche
+principali delle pipe. Per poter effettuare la conversione di un PDF infatti è
+necessario, per la struttura del formato, potersi spostare (con \func{lseek})
+all'interno del file da convertire; se si esegue la conversione con \cmd{gs} su
+un file regolare non ci sono problemi, una pipe però è rigidamente
+sequenziale, e l'uso di \func{lseek} su di essa fallisce sempre con un errore
+di \macro{ESPIPE}, rendendo impossibile la conversione.  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 un procedimento diverso, eseguendo
+prima la conversione (sempre con \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, è
+  infatti molto facile da manipolare, dato che usa caratteri ASCII per
+  memorizzare le immagini, anche se per questo è estremamente inefficiente.}
+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 (con \cmd{pnm2png}).
 
 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
@@ -473,7 +470,7 @@ Alla fine tutto quello che resta da fare 
 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
+ciclo che chiuda, nell'ordine inverso rispetto a quello in cui le si sono
 create, tutte le pipe create con \func{pclose}.
 
 
@@ -513,83 +510,317 @@ nel qual caso l'apertura del capo in lettura avr
 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.}
+In Linux è possibile aprire le fifo anche in lettura/scrittura,\footnote{lo
+  standard POSIX lascia indefinito il comportamento in questo caso.}
+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
+situazioni di stallo.\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 la loro caratteristica di essere accessibili attraverso il filesystem, è
 piuttosto frequente l'utilizzo di una fifo come canale di comunicazione nelle
-situazioni un processo deve ricevere informazioni dagli altri. In questo caso
-è fondamentale che le operazioni di scrittura siano atomiche; per questo si
-deve sempre tenere presente che questo è vero soltanto fintanto che non si
-supera il limite delle dimensioni di \macro{PIPE\_BUF} (si ricordi quanto
-detto in \secref{sec:ipc_pipes}).
-
-A parte il precedente, che resta probabilmente il più comune, Stevens riporta
-in \cite{APUE} altre due casistiche principali per l'uso delle fifo:
+situazioni un processo deve ricevere informazioni da altri. In questo caso è
+fondamentale che le operazioni di scrittura siano atomiche; per questo si deve
+sempre tenere presente che questo è vero soltanto fintanto che non si supera
+il limite delle dimensioni di \macro{PIPE\_BUF} (si ricordi quanto detto in
+\secref{sec:ipc_pipes}).
+
+A parte il caso precedente, che resta probabilmente il più comune, Stevens
+riporta in \cite{APUE} altre due casistiche principali per l'uso delle fifo:
 \begin{itemize}
 \item Da parte dei comandi di shell, per evitare la creazione di file
   temporanei quando si devono inviare i dati di uscita di un processo
   sull'input di parecchi altri (attraverso l'uso del comando \cmd{tee}).
   
-\item Come canale di comunicazione fra un client ed un server (il modello
+\item Come canale di comunicazione fra client ed server (il modello
   \textit{client-server} è illustrato in \secref{sec:net_cliserv}).
 \end{itemize}
 
-Nel primo caso quello che si fa è creare tante pipe quanti sono i processi a
-cui i vogliono inviare i dati, da usare come standard input per gli stessi; una
-volta che li si saranno posti in esecuzione ridirigendo lo standard input si
-potrà eseguire il processo iniziale replicandone, con il comando \cmd{tee},
-l'output sulle pipe.
+Nel primo caso quello che si fa è creare tante fifo, da usare come standard
+input, quanti sono i processi a cui i vogliono inviare i dati, questi ultimi
+saranno stati posti in esecuzione ridirigendo lo standard input dalle fifo, si
+potrà poi eseguire il processo che fornisce l'output replicando quest'ultimo,
+con il comando \cmd{tee}, sulle varie fifo.
 
 Il secondo caso è relativamente semplice qualora si debba comunicare con un
-processo alla volta (nel qual caso basta usare due pipe, una per leggere ed
+processo alla volta (nel qual caso basta usare due fifo, una per leggere ed
 una per scrivere), le cose diventano invece molto più complesse quando si
 vuole effettuare una comunicazione fra il server ed un numero imprecisato di
 client; se il primo infatti può ricevere le richieste attraverso una fifo
-``nota'', per le risposte non si può fare altrettanto, dato che per la
+``nota'', per le risposte non si può fare altrettanto, dato che, per la
 struttura sequenziale delle fifo, i client dovrebbero sapere, prima di
 leggerli, quando i dati inviati sono destinati a loro.
 
 Per risolvere questo problema, si può usare un'architettura come quella
-illustrata da Stevens in \cite{APUE}, in cui le risposte vengono inviate su
-fifo temporanee identificate dal \acr{pid} dei client, ma in ogni caso il
-sistema è macchinoso e continua ad avere vari inconvenienti\footnote{lo stesso
-  Stevens nota come sia impossibile per il server sapere se un client è andato
-  in crash, con la possibilità di far restare le fifo temporanee sul
-  filesystem, come sia necessario intercettare \macro{SIGPIPE} dato che un
-  client può terminare dopo aver fatto una richiesta, ma prima che la risposta
-  sia inviata, e come occorra gestire il caso in cui non ci sono client attivi
-  (e la lettura dalla fifo nota restituisca al serve un end-of-file.}; in
-generale infatti l'interfaccia delle fifo non è adatta a risolvere questo tipo
-di problemi, che possono essere affrontati in maniera più semplice ed efficace
-o usando i \textit{socket}\index{socket} (che tratteremo in dettaglio a
-partire da \capref{cha:socket_intro}) o ricorrendo a diversi meccanismi di
-comunicazione, come quelli che esamineremo in \secref{sec:ipc_sysv}.
+illustrata in \figref{fig:ipc_fifo_server_arch} in cui i client inviano le
+richieste al server su una fifo nota mentre le risposte vengono reinviate dal
+server a ciascuno di essi su una fifo temporanea creata per l'occazione.
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[height=9cm]{img/fifoserver}
+  \caption{Schema dell'utilizzo delle fifo nella realizzazione di una
+  architettura di comunicazione client/server.}
+  \label{fig:ipc_fifo_server_arch}
+\end{figure}
+
+Come esempio di uso questa architettura e dell'uso delle fifo, abbiamo scritto
+un server di \textit{fortunes}, che restituisce, alle richieste di un client,
+un detto a caso estratto da un insieme di frasi; sia il numero delle frasi
+dell'insieme, che i file da cui esse vengono lette all'avvio, sono importabili
+da riga di comando. Il corpo principale del server è riportato in
+\figref{fig:ipc_fifo_server}, dove si è tralasciata la parte che tratta la
+gestione delle opzioni a riga di comando, che effettua il settaggio delle
+variabili \var{fortunefilename}, che indica il file da cui leggere le frasi,
+ed \var{n}, che indica il numero di frasi tenute in memoria, ad un valore
+diverso da quelli preimpostati. Il codice completo è nel file
+\file{FortuneServer.c}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+char *fifoname = "/tmp/fortune.fifo";
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+    int i, n = 0;
+    char *fortunefilename = "/usr/share/games/fortunes/italia";
+    char **fortune;
+    char line[80];
+    int fifo_server, fifo_client;
+    int nread;
+    ...
+    if (n==0) usage();          /* if no pool depth exit printing usage info */
+    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
+    Signal(SIGINT, HandSIGTERM);
+    Signal(SIGQUIT, HandSIGTERM);
+    i = FortuneParse(fortunefilename, fortune, n);          /* parse phrases */
+    if (mkfifo(fifoname, 0622)) {  /* create well known fifo if does't exist */
+        if (errno!=EEXIST) {
+            perror("Cannot create well known fifo");
+            exit(1);
+        }
+    }
+    /* open fifo two times to avoid EOF */
+    fifo_server = open(fifoname, O_RDONLY);
+    if (fifo_server < 0) {
+        perror("Cannot open read only well known fifo");
+        exit(1);
+    }
+    if (open(fifoname, O_WRONLY) < 0) {                        
+        perror("Cannot open write only well known fifo");
+        exit(1);
+    }
+    /* Main body: loop over requests */
+    while (1) {
+        nread = read(fifo_server, line, 79);                 /* read request */
+        if (nread < 0) {
+            perror("Read Error");
+            exit(1);
+        }
+        line[nread] = 0;                       /* terminate fifo name string */
+        n = random() % i;                             /* select random value */
+        fifo_client = open(line, O_WRONLY);              /* open client fifo */
+        if (fifo_client < 0) {
+            perror("Cannot open");
+            exit(1);
+        }
+        nread = write(fifo_client,                           /* write phrase */
+                      fortune[n], strlen(fortune[n])+1);
+        close(fifo_client);                             /* close client fifo */
+    }
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del server di \textit{fortunes}
+    basato sulle fifo.}
+  \label{fig:ipc_fifo_server}
+\end{figure}
+
+Il server richiede (\texttt{\small 12}) che sia stata impostata una dimensione
+dell'insieme delle frasi non nulla, dato che l'inizializzazione del vettore
+\var{fortune} avviene solo quando questa dimensione viene specificata, la
+presenza di un valore nullo provoca l'uscita dal programma attraverso la
+routine (non riportata) che ne stampa le modalità d'uso.  Dopo di che installa
+(\texttt{\small 13--15}) la funzione che gestisce i segnali di interruzione
+(anche questa non è riportata in \figref{fig:ipc_fifo_server}) che si limita a
+rimuovere dal filesystem la fifo usata dal server per comunicare.
+
+Terminata l'inizializzazione (\texttt{\small 16}) si effettua la chiamata alla
+funzione \code{FortuneParse} che legge dal file specificato in
+\var{fortunefilename} le prime \var{n} frasi e le memorizza (allocando
+dinamicamente la memoria necessaria) nel vettore di puntatori \var{fortune}.
+Anche il codice della funzione non è riportato, in quanto non direttamente
+attinente allo scopo dell'esempio.
+
+Il passo successivo (\texttt{\small 17--22}) è quello di creare con
+\func{mkfifo} la fifo nota sulla quale il server ascolterà le richieste,
+qualora si riscontri un errore il server uscirà (escludendo ovviamente il caso
+in cui la funzione \func{mkfifo} fallisce per la precedente esistenza della
+fifo).
+
+Una volta che si è certi che la fifo di ascolto esiste si procede
+(\texttt{\small 23--32}) alla sua apertura. Questo viene fatto due volte
+per evitare di dover gestire all'interno del ciclo principale il caso in cui
+il server è in ascolto ma non ci sono client che effettuano richieste.
+Si ricordi infatti che quando una fifo è aperta solo dal capo in lettura,
+l'esecuzione di \func{read} ritorna con zero byte (si ha cioè una condizione
+di end-of-file).
+
+Nel nostro caso la prima apertura si bloccherà fintanto che un qualunque
+client non apre a sua volta la fifo nota in scrittura per effettuare la sua
+richiesta. Pertanto all'inizio non ci sono probelmi, il client però, una volta
+ricevuta la risposta, uscirà, chiudendo tutti i file aperti, compresa la fifo.
+A questo punto il server resta (se non ci sono altri client che stanno
+effettuando richieste) con la fifo chiusa sul lato in lettura e a questo punto
+\func{read} non si bloccherà in attesa di input, ma ritornerà in continuazione
+restituendo un end-of-file.\footnote{Si è usata questa tecnica per
+  compatibilità, Linux infatti supporta l'apertura delle fifo in
+  lettura/scrittura, per cui si sarebbe potuto effettuare una singola apertura
+  con \macro{O\_RDWR}, la doppia apertura comunque ha il vantaggio che non si
+  può scrivere per errore sul capo aperto in sola lettura.}
+
+Per questo motivo, dopo aver eseguito l'apertura in lettura (\texttt{\small
+  24--28}),\footnote{di solito si effettua l'apertura del capo in lettura in
+  modalità non bloccante, per evitare il rischio di uno stallo (se nessuno
+  apre la fifo in scrittura il processo non ritornerà mai dalla \func{open})
+  che nel nostro caso non esiste, mentre è necessario potersi bloccare in
+  lettura in attesa di una richiesta.} si esegue una seconda apertura in
+scrittura (\texttt{\small 29--32}), scartando il relativo file descriptor che
+non sarà mai usato, ma lasciando la fifo comunque aperta anche in scrittura,
+cosicché le successive possano bloccarsi.
+
+A questo punto si può entrare nel ciclo principale del programma che fornisce
+le risposte ai client (\texttt{\small 34--50}), che viene eseguito
+indefinitamente (l'uscita del server viene effettuata inviando un segnale, in
+modo da passare attraverso la routine di chiusura che cancella la fifo). 
+
+Il server è progettato per accettare come richieste dai client delle stringhe
+che contengono il nome della fifo sulla quale deve essere inviata la risposta.
+Per cui prima (\texttt{\small 35--39}) si esegue la lettura dalla stringa di
+richiesta dalla fifo nota (che a questo punto si bloccherà tutte le volte che
+non ci sono richieste). Dopo di che, una volta terminata la stringa
+(\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero casuale per
+ricavare la frase da inviare, si procederà (\texttt{\small 42--46})
+all'apertura della fifo per la risposta, che \texttt{\small 47--48}) poi vi
+sarà scritta. Infine (\texttt{\small 49}) si chiude la fifo di risposta che
+non serve più. 
+
+Il codice del client è invece riportato in \figref{fig:ipc_fifo_client}, anche
+in questo caso si è omessa la gestione delle opzioni e la funzione che stampa
+a video le informazioni di utilizzo ed esce, riportando solo la sezione
+principale del programma e le definizioni delle variabili. Il codice completo
+è nel file \file{FortuneClient.c} dei sorgenti allegati.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+    int n = 0;
+    char *fortunefilename = "/tmp/fortune.fifo";
+    char line[80];
+    int fifo_server, fifo_client;
+    char fifoname[80];
+    int nread;
+    char buffer[PIPE_BUF];
+    ...
+    snprintf(fifoname, 80, "/tmp/fortune.%d", getpid());     /* compose name */
+    if (mkfifo(fifoname, 0622)) {                        /* open client fifo */
+        if (errno!=EEXIST) {
+            perror("Cannot create well known fifo");
+            exit(-1);
+        }
+    }
+    fifo_server = open(fortunefilename, O_WRONLY);       /* open server fifo */
+    if (fifo_server < 0) {
+        perror("Cannot open well known fifo");
+        exit(-1);
+    }
+    nread = write(fifo_server, fifoname, strlen(fifoname)+1);  /* write name */
+    close(fifo_server);                                 /* close server fifo */
+    fifo_client = open(fifoname, O_RDONLY);              /* open client fifo */
+    if (fifo_client < 0) {
+        perror("Cannot open well known fifo");
+        exit(-1);
+    }
+    nread = read(fifo_client, buffer, sizeof(buffer));        /* read answer */
+    printf("%s", buffer);                                   /* print fortune */
+    close(fifo_client);                                      /* close client */
+    close(fifo_server);                                      /* close server */
+    unlink(fifoname);                                  /* remove client fifo */
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del client di \textit{fortunes}
+    basato sulle fifo.}
+  \label{fig:ipc_fifo_client}
+\end{figure}
+
+La prima istruzione (\texttt{\small 12}) compone il nome della fifo che dovrà
+essere utilizzata per ricevere la risposta dal server.  Si usa il \acr{pid}
+del processo per essere sicuri di avere un nome univoco; dopo di che
+(\texttt{\small 13-18}) si procede alla creazione del relativo file, uscendo
+in caso di errore (a meno che il file non sia già presente sul filesystem).
+
+A questo punto il client può effettuare l'interrogazione del server, per
+questo prima si apre la fifo nota (\texttt{\small 19--23}), e poi ci si scrive
+(\texttt{\small 24}) la stringa composta in precedenza, che contiene il nome
+della fifo da utilizzare per la risposta. Infine si richiude la fifo del
+server che a questo punto non serve più (\texttt{\small 25}).
+
+Inoltrata la richiesta si può passare alla lettura della risposta; anzitutto
+si apre (\texttt{\small 26--30}) la fifo appena creata, da cui si deve
+riceverla, dopodiché si effettua una lettura (\texttt{\small 31})
+nell'apposito buffer; si è supposto, come è ragionevole, che le frasi inviate
+dal server siano sempre di dimensioni inferiori a \macro{PIPE\_BUF},
+tralasciamo la gestione del caso in cui questo non è vero. Infine si stampa
+(\texttt{\small 32}) a video la risposta, si chiude (\texttt{\small 33}) la
+fifo e si cancella (\texttt{\small 34}) il relativo file.
+
+Si noti come la fifo per la risposta sia stata aperta solo dopo aver inviato
+la richiesta, se non si fosse fatto così si avrebbe avuto uno stallo, in
+quanto senza la richiesta, il server non avrebbe potuto aprirne il capo in
+scrittura e l'apertura si sarebbe bloccata indefinitamente.
+
+Benché il nostro sistema client-server funzioni, la sua struttura è piuttosto
+complessa e continua ad avere vari inconvenienti\footnote{lo stesso Stevens,
+  che esamina questa architettura in \cite{APUE}, nota come sia impossibile
+  per il server sapere se un client è andato in crash, con la possibilità di
+  far restare le fifo temporanee sul filesystem, di come sia necessario
+  intercettare \macro{SIGPIPE} dato che un client può terminare dopo aver
+  fatto una richiesta, ma prima che la risposta sia inviata (cosa che nel
+  nostro esempio non è stata fatta).}; in generale infatti l'interfaccia delle
+fifo non è adatta a risolvere questo tipo di problemi, che possono essere
+affrontati in maniera più semplice ed efficace o usando i
+\textit{socket}\index{socket} (che tratteremo in dettaglio a partire da
+\capref{cha:socket_intro}) o ricorrendo a meccanismi di comunicazione diversi,
+come quelli che esamineremo in seguito.
 
 
 
 \section{La comunicazione fra processi di System V}
 \label{sec:ipc_sysv}
 
-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; per cui una situazione in cui un processo scrive
-qualcosa che molti altri devono poter leggere non può essere implementata in
-maniera semplice con una pipe.
-
-Per superarne questi limiti nello sviluppo di System V vennero introdotti una
-serie di nuovi oggetti di comunicazione e relative interfacce di
-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
+Benché le pipe e le fifo siano ancora ampiamente usate, esse scontano il
+limite fondamentale che il meccanismo di comunicazione che forniscono è
+rigidamente sequenziale: una situazione in cui un processo scrive qualcosa che
+molti altri devono poter leggere non può essere implementata con una pipe.
+
+Per questo nello sviluppo di System V vennero introdotti una serie di nuovi
+oggetti per la comunicazione fra processi ed una nuova interfaccia di
+programmazione, che fossero in grado di garantire una maggiore flessibilità.
+In questa sezione esamineremo come Linux supporta quello che viene ormai
+chiamato il \textsl{Sistema di comunicazione inter-processo} di System V, o
 \textit{System V IPC (Inter-Process Comunication)}.
 
 
@@ -597,43 +828,590 @@ esamineremo quello che viene ormai chiamato il \textsl{Sistema di
 \subsection{Considerazioni generali}
 \label{sec:ipc_sysv_generic}
 
-La principale caratteristica, (che può essere considerato anche uno dei suoi
-maggiori difetti) del sistema di IPC di System V è che è basato su oggetti che
-risiedono nel kernel, a differenza delle pipe che sono locali ai processi che
-condividono lo stesso file descriptor, e delle fifo, cui invece si accede
-attraverso il filesystem. 
-
-Ad essi si accede attraverso un identificatore generato autonomamente dal
-kernel alla loro creazione (come un numero intero progressivo, in maniera
-simile a quanto fatto per i \acr{pid}). A ciascun oggetto è pure associata una
-chiave, che di norma viene usata per ricavare l'identificatore. 
-
-Una seconda caratteristica di questi oggetti è che non prevedono un numero di
+La principale caratteristica del sistema di IPC di System V è quella di essere
+basato su oggetti permanenti che risiedono nel kernel. Questi, a differenza di
+quanto avviene per i file descriptor, non mantengono un contatore dei
+riferimenti, e non vengono cancellati dal sistema una volta che non sono più
+in uso. 
+
+Questo comporta due problemi: il primo è che, al contrario di quanto avviene
+per pipe e fifo, la memoria allocata per questi oggetti non viene rilasciata
+automaticamente quando nessuno li vuole più utilizzare, ed essi devono essere
+cancellati esplicitamente, se non si vuole che restino attivi fino al riavvio
+del sistema. Il secondo è che, dato che non c'è un contatore di riferimenti,
+essi possono essere cancellati anche se ci sono dei processi che li stanno
+utilizzando, con tutte le conseguenze (negative) del caso.
+
+Gli oggetti usati nel System V IPC vengono creati direttamente dal kernel, e
+sono accessibili solo specificando il relativo \textsl{identificatore}. Questo
+è un numero progressivo (un po' come il \acr{pid} dei processi) che il kernel
+assegna a ciascuno di essi quanto vengono creati (sul procedimento di
+assegnazione torneremo in \secref{sec:ipc_sysv_id_use}). L'identificatore
+viene restituito dalle funzioni che creano l'oggetto, ed è quindi locale al
+processo che le ha eseguite. Dato che l'identificatore viene assegnato
+dinamicamente dal kernel non è possibile prevedere quale sarà, ne utilizzare
+un qualche valore statico, si pone perciò il problema di come processi diversi
+possono accedere allo stesso oggetto.
+
+Per risolvere il problema il kernel associa a ciascun oggetto una struttura
+\var{ipc\_perm}; questa contiene una \textsl{chiave}, identificata da una
+variabile del tipo primitivo \type{key\_t}, che viene specificata in fase di
+creazione e tramite la quale è possibile ricavare l'identificatore. La
+struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm},
+contiene anche le varie proprietà associate all'oggetto. 
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm ]{}
+struct ipc_perm
+{
+    key_t key;                        /* Key.  */
+    uid_t uid;                        /* Owner's user ID.  */
+    gid_t gid;                        /* Owner's group ID.  */
+    uid_t cuid;                       /* Creator's user ID.  */
+    gid_t cgid;                       /* Creator's group ID.  */
+    unsigned short int mode;          /* Read/write permission.  */
+    unsigned short int seq;           /* Sequence number.  */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{ipc\_perm}, come definita in \file{sys/ipc.h}.} 
+  \label{fig:ipc_ipc_perm}
+\end{figure}
 
+Usando la stessa chiave due processi diversi possono ricavare l'identificatore
+associato ad un oggetto ed accedervi. Il problema che sorge a questo punto è
+come devono fare per accordarsi sull'uso di una stessa chiave. Se i processi
+sono \textsl{parenti} la soluzione è relativamente semplice, in tal caso
+infatti si può usare il valore speciale \texttt{IPC\_PRIVATE} per creare un
+nuovo oggetto nel processo padre, l'identificatore così ottenuto sarà
+disponibile in tutti i figli, e potrà essere passato come parametro attraverso
+una \func{exec}.
+
+Però quando i processi non sono \textsl{parenti} (come capita tutte le volte
+che si ha a che fare con un sistema client-server) tutto questo non è
+possibile; si potrebbe comunque salvare l'identificatore su un file noto, ma
+questo ovviamente comporta lo svantaggio di doverselo andare a rileggere.  Una
+alternativa più efficace è quella che i programmi usino un valore comune per
+la chiave (che ad esempio può essere dichiarato in un header comune), ma c'è
+sempre il rischio che questa chiave possa essere stata già utilizzata da
+qualcun altro.  Dato che non esiste una convenzione su come assegnare queste
+chiavi in maniera univoca l'interfaccia mette a disposizione una funzione,
+\func{ftok}, che permette di ottenere una chiave specificando il nome di un
+file ed un numero di versione; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  
+  \funcdecl{key\_t ftok(const char *pathname, int proj\_id)}
+  
+  Restituisce una chiave per identificare un oggetto del System V IPC.
+  
+  \bodydesc{La funzione restituisce la chiave in caso di successo e -1
+  altrimenti, nel qual caso \var{errno} viene settata ad uno dei possibili
+  codici di errore di \func{stat}.}
+\end{functions}
+
+La funzione determina un valore della chiave sulla base di \param{pathname},
+che deve specificare il pathname di un file effettivamente esistente e di un
+numero di progetto \param{proj\_id)}, che di norma viene specificato come
+carattere, dato che ne vengono utilizzati solo gli 8 bit meno
+significativi.\footnote{nelle libc4 e libc5, come avviene in SunOS,
+  l'argomento \param{proj\_id} è dichiarato tipo \ctyp{char}, le \acr{glibc}
+  usano il prototipo specificato da XPG4, ma vengono lo stesso utilizzati gli
+  8 bit meno significativi.}
+
+Il problema è che anche così non c'è la sicurezza che il valore della chiave
+sia univoco, infatti esso è costruito combinando il byte di \param{proj\_id)}
+con i 16 bit meno significativi dell'inode del file \param{pathname} (che
+vengono ottenuti attraverso \func{stat}, da cui derivano i possibili errori),
+e gli 8 bit meno significativi del numero del dispositivo su cui è il file.
+Diventa perciò relativamente facile ottenere delle collisioni, specie se i
+file sono su dispositivi con lo stesso \textit{minor number}, come
+\file{/dev/hda1} e \file{/dev/sda1}.
+
+In genere quello che si fa è utilizzare un file comune usato dai programmi che
+devono comunicare (ad esempio un haeder comune, o uno dei programmi che devono
+usare l'oggetto in questione), utilizzando il numero di progetto per ottenere
+le chiavi che interessano. In ogni caso occorre sempre controllare, prima di
+creare un oggetto, che la chiave non sia già stata utilizzata. Se questo va
+bene in fase di creazione, le cose possono complicarsi per i programmi che
+devono solo accedere, in quanto, a parte gli eventuali controlli sugli altri
+attributi di \var{ipc\_perm}, non esiste una modalità semplice per essere
+sicuri che l'oggetto associato ad una certa chiave sia stato effettivamente
+creato da chi ci si aspetta.
+
+Questo è, insieme al fatto che gli oggetti sono permanenti e non mantengono un
+contatore di riferimenti per la cancellazione automatica, il principale
+problema del sistema di IPC di System V. Non esiste infatti una modalità
+chiara per identificare un oggetto, come sarebbe stato se lo si fosse
+associato ad in file, e tutta l'interfaccia è inutilmente complessa.  Per
+questo ne è stata effettuata una revisione completa nello standard POSIX.1b,
+che tratteremo in \secref{sec:ipc_posix}.
+
+
+\subsection{Il controllo di accesso}
+\label{sec:ipc_sysv_access_control}
+
+Oltre alle chiavi, abbiamo visto che ad ogni oggetto sono associate in
+\var{ipc\_perm} ulteriori informazioni, come gli identificatori del creatore
+(nei campi \var{cuid} e \var{cgid}) e del proprietario (nei campi \var{uid} e
+\var{gid}) dello stesso, e un insieme di permessi (nel campo \var{mode}). In
+questo modo è possibile definire un controllo di accesso sugli oggetti di IPC,
+simile a quello che si ha per i file (vedi \secref{sec:file_perm_overview}).
+
+Benché questo controllo di accesso sia molto simile a quello dei file, restano
+delle importanti differenze. La prima è che il permesso di esecuzione non
+esiste (e se specificato viene ignorato), per cui si può parlare solo di
+permessi di lettura e scrittura (nel caso dei semafori poi quest'ultimo è più
+propriamente un permesso di modifica). I valori di \var{mode} sono gli stessi
+ed hanno lo stesso significato di quelli riportati in
+\secref{tab:file_mode_flags}\footnote{se però si vogliono usare le costanti
+  simboliche ivi definite occorrerà includere il file \file{sys/stat.h},
+  alcuni sistemi definiscono le costanti \macro{MSG\_R} (\texttt{0400}) e
+  \macro{MSG\_W} (\texttt{0200}) per indicare i permessi base di lettura e
+  scrittura per il proprietario, da utilizzare, con gli opportuni shift, pure
+  per il gruppo e gli altri, in Linux, visto la loro scarsa utilità, queste
+  costanti non sono definite.} e come per i file definiscono gli accessi per
+il proprietario, il suo gruppo e tutti gli altri.
+
+Quando l'oggetto viene creato i campi \var{cuid} e \var{uid} di
+\var{ipc\_perm} ed i campi \var{cgid} e \var{gid} vengono settati
+rispettivamente al valore dell'userid e del groupid effettivo del processo che
+ha chiamato la funzione, ma, mentre i campi \var{uid} e \var{gid} possono
+essere cambiati, i campi \var{cuid} e \var{cgid} restano sempre gli stessi.
+
+Il controllo di accesso è effettuato a due livelli. Il primo livello è nelle
+funzioni che richiedono l'identificatore di un oggetto data la chiave. Queste
+specificano tutte un argomento \param{flag}, in tal caso quando viene
+effettuata la ricerca di una chiave, qualora \param{flag} specifichi dei
+permessi, questi vengono controllati e l'identificatore viene restituito solo
+se corrispondono a quelli dell'oggetto. Se ci sono dei permessi non presenti
+in \var{mode} l'accesso sarà negato. Questo controllo però è di utilità
+indicativa, dato che è sempre possibile specificare per \param{flag} un valore
+nullo, nel qual caso l'identificatore sarà restituito comunque.
+
+Il secondo livello di controllo è quello delle varie funzioni che accedono
+direttamente (in lettura o scrittura) all'oggetto. In tal caso lo schema dei
+controlli è simile a quello dei file, ed avviene secondo questa sequenza:
+\begin{itemize}
+\item se il processo ha i privilegi di amministratore l'accesso è sempre
+  consentito. 
+\item se l'userid effettivo del processo corrisponde o al valore del campo
+  \var{cuid} o a quello del campo \var{uid} ed il permesso per il proprietario
+  in \var{mode} è appropriato\footnote{per appropriato si intende che è
+    settato il permesso di scrittura per le operazioni di scrittura e quello
+    di lettura per le operazioni di lettura.} l'accesso è consentito.
+\item se il groupid effettivo del processo corrisponde o al
+  valore del campo \var{cgid} o a quello del campo \var{gid} ed il permesso
+  per il gruppo in \var{mode} è appropriato l'accesso è consentito.
+\item se il permesso per gli altri è appropriato l'accesso è consentito.
+\end{itemize}
+solo se tutti i controlli elencati falliscono l'accesso è negato. Si noti che
+a differenza di quanto avviene per i permessi dei file, fallire in uno dei
+passi elencati non comporta il fallimento dell'accesso. Un'ulteriore
+differenza rispetto a quanto avviene per i file è che per gli oggetti di IPC
+il valore di \var{umask} (si ricordi quanto esposto in
+\secref{sec:file_umask}) non ha alcun significato.
+
+
+\subsection{Gli identificatori ed il loro utilizzo}
+\label{sec:ipc_sysv_id_use}
+
+L'unico campo di \var{ipc\_perm} del quale non abbiamo ancora parlato è
+\var{seq}, che in \figref{fig:ipc_ipc_perm} è qualificato con un criptico
+``\textsl{numero di sequenza}'', ne parliamo adesso dato che esso è
+strettamente attinente alle modalità con cui il kernel assegna gli
+identificatori degli oggetti del sistema di IPC.
+
+Quando il sistema si avvia, alla creazione di ogni nuovo oggetto di IPC viene
+assegnato un numero progressivo, pari al numero di oggetti di quel tipo
+esistenti. Se il comportamento fosse sempre questo sarebbe identico a quello
+usato nell'assegnazione dei file descriptor nei processi, ed i valori degli
+identificatori tenderebbero ad essere riutilizzati spesso e restare di piccole
+dimensioni (inferiori al numero massimo di oggetti disponibili).
+
+Questo va benissimo nel caso dei file descriptor, che sono locali ad un
+processo, ma qui il comportamento varrebbe per tutto il sistema, e per
+processi del tutto scorrelati fra loro. Così si potrebbero avere situazioni
+come quella in cui un server esce e cancella le sue code di messaggi, ed il
+relativo identificatore viene immediatamente assegnato a quelle di un altro
+server partito subito dopo, con la possibilità che i client del primo non
+facciano in tempo ad accorgersi dell'avvenuto, e finiscano con l'interagire
+con gli oggetti del secondo, con conseguenze imprevedibili.
+
+Proprio per evitare questo tipo di situazioni il sistema usa il valore di
+\var{req} per provvedere un meccanismo che porti gli identificatori ad
+assumere tutti i valori possibili, rendendo molto più lungo il periodo in cui
+un identificatore può venire riutilizzato.
+
+Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino
+  al kernel 2.2.x questi valori, definiti dalle costanti \macro{MSGMNI},
+  \macro{SEMMNI} e \macro{SHMMNI}, potevano essere cambiati (come tutti gli
+  altri limiti relativi al \textit{System V IPC}) solo con una ricompilazione
+  del kernel, andando a modificarne la definizione nei relativi haeder file.
+  A partire dal kernel 2.4.x è possibile cambiare questi valori a sistema
+  attivo scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di
+  \file{/proc/sys/kernel} o con l'uso di \texttt{syscntl}.} e per ciascuno di
+essi viene mantenuto in \var{seq} un numero di sequenza progressivo che viene
+incrementato di uno ogni volta che l'oggetto viene cancellato. Quando
+l'oggetto viene creato usando uno spazio che era già stato utilizzato in
+precedenza per restituire l'identificatore al numero di oggetti presenti viene
+sommato il valore di \var{seq} moltiplicato per il numero massimo di oggetti
+di quel tipo,\footnote{questo vale fino ai kernel della serie 2.2.x, dalla
+  serie 2.4.x viene usato lo stesso fattore per tutti gli oggetti, esso è dato
+  dalla costante \macro{IPCMNI}, definita in \file{include/linux/ipc.h}, che
+  indica il limite massimo per il numero di tutti oggetti di IPC, ed il cui
+  valore è 32768.}  si evita così il riutilizzo degli stessi numeri, e si fa
+sì che l'identificatore assuma tutti i valori possibili.
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+    ...
+    switch (type) {
+    case 'q':   /* Message Queue */
+        debug("Message Queue Try\n");
+        for (i=0; i<n; i++) {
+            id = msgget(IPC_PRIVATE, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            msgctl(id, IPC_RMID, NULL);
+        }
+        break;
+    case 's':   /* Semaphore */
+        debug("Semaphore\n");
+        for (i=0; i<n; i++) {
+            id = semget(IPC_PRIVATE, 1, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            semctl(id, 0, IPC_RMID);
+        }
+        break;
+    case 'm':   /* Shared Memory */
+        debug("Shared Memory\n");
+        for (i=0; i<n; i++) {
+            id = shmget(IPC_PRIVATE, 1000, IPC_CREAT|0666);
+            printf("Identifier Value %d \n", id);
+            shmctl(id, IPC_RMID, NULL);
+        }
+        break;
+    default:    /* should not reached */
+        return -1;
+    }
+    return 0;
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del programma di test per l'assegnazione degli
+    identificatori degli oggetti di IPC \file{IPCTestId.c}.}
+  \label{fig:ipc_sysv_idtest}
+\end{figure}
 
+In \figref{fig:ipc_sysv_idtest} è riportato il codice di un semplice programma
+di test che si limita a creare un oggetto (specificato a riga di comando),
+stamparne il numero di identificatore e cancellarlo per un numero specificato
+di volte. Al solito non si è riportato il codice della gestione delle opzioni
+a riga di comando, che permette di specificare quante volte effettuare il
+ciclo \var{n}, e su quale tipo di oggetto eseguirlo.
+
+La figura non riporta il codice di selezione delle opzioni, che permette di
+inizializzare i valori delle variabili \var{type} al tipo di oggetto voluto, e
+\var{n} al numero di volte che si vuole effettuare il ciclo di creazione,
+stampa, cancellazione. I valori di default sono per l'uso delle code di
+messaggi e un ciclo di 5 volte. Se si lancia il comando si otterrà qualcosa
+del tipo:
+\begin{verbatim}
+piccardi@gont sources]$ ./ipctestid
+Identifier Value 0 
+Identifier Value 32768 
+Identifier Value 65536 
+Identifier Value 98304 
+Identifier Value 131072 
+\end{verbatim}%$
+il che ci mostra che abbiamo un kernel della serie 2.4.x nel quale non avevamo
+ancora usato nessuna coda di messaggi. Se ripetiamo il comando otterremo
+ancora:
+\begin{verbatim}
+[piccardi@gont sources]$ ./ipctestid
+Identifier Value 163840 
+Identifier Value 196608 
+Identifier Value 229376 
+Identifier Value 262144 
+Identifier Value 294912 
+\end{verbatim}%$
+che ci mostra come il valore di \var{seq} sia in effetti una quantità
+mantenuta staticamente all'interno del sistema.
 
 
 \subsection{Code di messaggi}
-\label{sec:ipc_messque}
+\label{sec:ipc_sysv_mq}
 
 Il primo oggetto introdotto dal \textit{System V IPC} è quello delle code di
-messaggi.
+messaggi.  Le code di messaggi sono oggetti analoghi alle pipe o alle fifo,
+anche se la loro struttura è diversa. La funzione che permette di ottenerne
+una è \func{msgget} ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/msg.h} 
+  
+  \funcdecl{int msgget(key\_t key, int flag)}
+  
+  Restituisce l'identificatore di una cosa di messaggi.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} viene settato ad uno dei
+    valori: 
+  \begin{errlist}
+  \item[\macro{EACCES}] Il processo chiamante non ha i privilegi per accedere
+  alla coda richiesta.  
+  \item[\macro{EEXIST}] Si è richiesta la creazione di una coda che già
+  esiste, ma erano specificati sia \macro{IPC\_CREAT} che \macro{IPC\_EXCL}. 
+  \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+  \item[\macro{ENOENT}] Si è cercato di ottenere l'identificatore di una coda
+    di messaggi specificando una chiave che non esiste e \macro{IPC\_CREAT}
+    non era specificato.
+  \item[\macro{ENOSPC}] Si è cercato di creare una coda di messaggi quando è
+    stato il limite massimo del sistema.
+  \end{errlist}
+  ed inoltre \macro{ENOMEM}.
+}
+\end{functions}
+
+Le funzione (come le analoghe che si usano per gli altri oggetti) serve sia a
+ottenere l'identificatore di una coda di messaggi esistente, che a crearne una
+nuova. L'argomento \param{key} specifica la chiave che è associata
+all'oggetto, eccetto il caso in cui si specifichi il valore
+\macro{IPC\_PRIVATE}, nel qual caso la coda è creata ex-novo e non vi è
+associata alcuna chiave, il processo (ed i suoi eventuali figli) potranno
+farvi riferimento solo attraverso l'identificatore.
+
+Se invece si specifica un valore diverso da \macro{IPC\_PRIVATE}\footnote{in
+  Linux questo significa un valore diverso da zero.} l'effetto della funzione
+dipende dal valore di \param{flag}, se questo è nullo la funzione si limita ad
+effettuare una ricerca sugli oggetti esistenti, restituendo l'identificatore
+se trova una corrispondenza, o fallendo con un errore di \macro{ENOENT} se non
+esiste o di \macro{EACCESS} se si sono specificati dei permessi non validi.
+
+Se invece si vuole creare una nuova coda di messaggi \param{flag} non può
+essere nullo e deve essere fornito come maschera binaria, impostando il bit
+corrispondente al valore \macro{IPC\_CREAT}. In questo caso i nove bit meno
+significativi di \param{flag} saranno usati come permessi per il nuovo
+oggetto, secondo quanto illustrato in \secref{sec:ipc_sysv_access_control}.
+Se si imposta anche il bit corrispondente a \macro{IPC\_EXCL} la funzione avrà
+successo solo se l'oggetto non esiste già, fallendo con un errore di
+\macro{EEXIST} altrimenti.
+
+Si tenga conto che l'uso di \macro{IPC\_PRIVATE} non impedisce ad altri
+processi di accedere alla coda (se hanno privilegi sufficienti) una volta che
+questi possano indovinare o ricavare (ad esempio per tentativi)
+l'identificatore ad essa associato. Per come sono implementati gli oggetti di
+IPC infatti non esiste una maniera che  garantisca l'accesso esclusivo ad una
+coda di messaggi.  Usare \macro{IPC\_PRIVATE} o macro{IPC\_CREAT} e
+\macro{IPC\_EXCL} per \param{flag} comporta solo la creazione di una nuova
+coda.
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|r|l|l|}
+    \hline
+    \textbf{Costante} & \textbf{Valore} & \textbf{File in \texttt{proc}}
+    & \textbf{Significato} \\
+    \hline
+    \hline
+    \macro{MSGMNI}&   16& \file{msgmni} & Numero massimo di code di
+                                          messaggi. \\
+    \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
+                                          messaggio.\\
+    \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima di una coda di 
+                                          messaggi.\\
+    \hline
+  \end{tabular}
+  \caption{Valori delle costanti associati ai limiti delle code di messaggi.}
+  \label{tab:ipc_msg_limits}
+\end{table}
+
+Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti
+negli header e corrispondenti alle prime tre costanti riportate in
+\tabref{tab:ipc_msg_limits}, come accennato però in Linux è possibile
+modificare questi limiti attraverso l'uso di \func{syscntl} o scrivendo nei
+file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}.
+
+
+\begin{figure}[htb]
+  \centering \includegraphics[width=15cm]{img/mqstruct}
+  \caption{Schema della struttura di una coda messaggi.}
+  \label{fig:ipc_mq_schema}
+\end{figure}
+
+
+Una coda di messaggi è costituita da una \textit{linked list};\footnote{una
+  \textit{linked list} è una tipica struttura di dati, organizzati in una
+  lista in cui ciascun elemento contiene un puntatore al successivo. In questo
+  modo la struttura è veloce nell'estrazione ed immissione dei dati dalle
+  estremità dalla lista (basta aggiungere un elemento in testa o in coda ed
+  aggiornare un puntatore), e relativamente veloce da attraversare in ordine
+  sequenziale (seguendo i puntatori), è invece relativamente lenta
+  nell'accesso casuale e nella ricerca.}  i nuovi messaggi vengono inseriti in
+coda alla lista e vengono letti dalla cima, in \figref{fig:ipc_mq_schema} si è
+riportato lo schema con cui queste strutture vengono mantenute dal
+kernel.\footnote{lo schema illustrato in figura è in realtà una semplificazione
+  di quanto usato fino ai kernel della serie 2.2.x, nei kernel della serie
+  2.4.x la gestione è effettuata in maniera diversa; ma esso illustra comunque
+  in maniera adeguata i principi di funzionamento delle code di messaggi.}
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct msqid_ds {
+    struct ipc_perm msg_perm;     /* structure for operation permission */
+    time_t msg_stime;             /* time of last msgsnd command */
+    time_t msg_rtime;             /* time of last msgrcv command */
+    time_t msg_ctime;             /* time of last change */
+    unsigned long int msg_cbytes; /* current number of bytes on queue */
+    msgqnum_t msg_qnum;           /* number of messages currently on queue */
+    msglen_t msg_qbytes;          /* max number of bytes allowed on queue */
+    pid_t msg_lspid;              /* pid of last msgsnd() */
+    pid_t msg_lrpid;              /* pid of last msgrcv() */
+    struct msg *msg_first;        /* first message on queue, unused  */
+    struct msg *msg_last;         /* last message in queue, unused */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{msgid\_ds}, associata a ciascuna coda di
+    messaggi. Si sono riportati i campi significativi definiti in
+    \file{sys/msg.h}, aggiungendo anche due campi interni, non visibili in
+    user space.}
+  \label{fig:ipc_msgid_sd}
+\end{figure}
+
+A ciascuna coda è associata una struttura \var{msgid\_ds}, la cui definizione
+è riportata in \secref{fig:ipc_msgid_sd}, il significato dei vari campi è
+riportato nella figura. In questa struttura il kernel\footnote{come accennato
+  questo vale fino ai kernel della serie 2.2.x, essa viene usata nei kernel
+  della serie 2.4.x solo per compatibilità in quanto è quella restituita dalle
+  funzioni dell'interfaccia.}  mantiene le principali informazioni riguardo lo
+stato corrente della coda. Quando si crea una nuova coda con \func{msgget}
+questa struttura viene inizializzata, in particolare il campo \var{msg\_perm}
+viene inizializzato come illustrato in \secref{sec:ipc_sysv_access_control},
+per quanto riguarda gli altri campi invece:
+\begin{itemize}
+\item i campi \var{msg\_qnum}, \var{msg\_lspid}, \var{msg\_lrpid},
+  \var{msg\_stime}, \var{msg\_rtime} sono inizializzati a 0
+\item il campo \var{msg\_ctime} viene settato al tempo corrente
+\item il campo \var{msg\_qbytes} al limite di sistema.
+\item i campi \var{msg\_first} e  \var{msg\_last} (che non vengono visti in
+  user space) sono inizializzati a \macro{NULL} essendo la coda vuota.
+\end{itemize}
+
+Una volta creata una coda di messaggi le operazioni di controllo vengono
+effettuate con la funzione \func{msgctl}, che (come le analoghe \func{semctl}
+e \func{shmctl}) fa le veci di quello che \func{ioctl} è per i file; il suo
+prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/msg.h} 
+  
+  \funcdecl{int msgctl(int msqid, int cmd, struct msqid\_ds *buf)}
+  
+  Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
+    errore, nel qual caso \var{errno} viene settato a:
+  \begin{errlist}
+  \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
+    non ha i privilegi di lettura sulla coda.
+  \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+  \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
+    il processo non ha i privilegi, o si è richiesto di aumentare il valore di
+    \var{msg\_qbytes} oltre il limite \macro{MSGMNB} senza essere
+    amministratore.
+  \end{errlist}
+  ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+
+La funzione permette di accedere ai valori della struttura \var{msqid\_ds},
+mantenuta all'indirizzo \param{buf}, per la coda specificata
+dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
+valore dell'argomento \param{cmd}, che specifica il tipo di azione da
+eseguire; i valori possibili sono:
+\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}}
+\item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
+  struttura indicata da \param{buf}. Occorre avere il permesso di lettura
+  sulla coda.
+\item[\macro{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con
+  effetto immediato. Tutti i processi che cercheranno di accedere alla coda
+  riceveranno un errore di \macro{EIDRM}, e tutti processi in attesa su
+  funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo
+  il medesimo errore. Questo comando può essere eseguito solo da un processo
+  con userid effettivo corrispondente al creatore a o al proprietario della
+  coda, o all'amministratore.
+\item[\macro{IPC\_SET}]
+\end{basedescript}
+
 
 \subsection{Semafori}
-\label{sec:ipc_semaph}
+\label{sec:ipc_sysv_sem}
 
 Il secondo oggetto introdotto dal \textit{System V IPC} è quello dei semafori.
+Un semaforo è uno speciale contatore che permette di controllare l'accesso a
+risorse condivise. La funzione che permette di ottenere un insieme di semafori
+è \func{semget} ed il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/sem.h} 
+  
+  \funcdecl{int semget(key\_t key, int nsems, int flag)}
+  
+  Restituisce l'identificatore di un semaforo.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} viene settato agli stessi
+    valori visti per \func{msgget}.}
+\end{functions}
+
+La funzione è del tutto analoga a \func{msgget} ed identico è l'uso degli
+argomenti \param{key} e \param{flag}, per cui non ripeteremo quanto detto al
+proposito in \secref{sec:ipc_sysv_mq}. L'argomento \param{nsems} permette di
+specificare quanti semafori deve contenere l'insieme qualora se ne richieda la
+creazione, e deve essere nullo quando si effettua una richiesta
+dell'identificatore di un insieme già esistente.
+
 
 
 \subsection{Memoria condivisa}
-\label{sec:ipc_shar_mem}
+\label{sec:ipc_sysv_shm}
 
 Il terzo oggetto introdotto dal \textit{System V IPC} è quello della memoria
-condivisa.
+condivisa. La funzione che permette di ottenerne uno è \func{shmget} ed il suo
+prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/shm.h}
+  
+  \funcdecl{int shmget(key\_t key, int size, int flag)}
+  
+  Restituisce l'identificatore di una memoria condivisa.
+  
+  \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+    in caso di errore, nel qual caso \var{errno} viene settato agli stessi
+    valori visti per \func{msgget}.}
+\end{functions}
 
+La funzione, come \func{semget}, è del tutto analoga a \func{msgget}, ed
+identico è l'uso degli argomenti \param{key} e \param{flag}. L'argomento
 
 
 
@@ -642,10 +1420,26 @@ condivisa.
 
 Lo standard POSIX.1b ha introdotto dei nuovi meccanismi di comunicazione,
 rifacendosi a quelli di System V, introducendo una nuova interfaccia che
-evitasse i principali problemi evidenziati in ...
+evitasse i principali problemi evidenziati in coda a
+\secref{sec:ipc_sysv_generic}.  
+
+
+
+\subsection{Considerazioni generali}
+\label{sec:ipc_posix_generic}
 
 
 
+\subsection{Code di messaggi}
+\label{sec:ipc_posix_mq}
+
+
+\subsection{Semafori}
+\label{sec:ipc_posix_sem}
+
+
+\subsection{Memoria condivisa}
+\label{sec:ipc_posix_shm}
 
 %%% Local Variables: 
 %%% mode: latex