Completata sezione sulla risoluzione di nomi ed indirizzi, iniziato a
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index ba47d11cd3007013384d2da885d37c6d54038121..22d6e76c6dbd0d88957e1c803de175c1eea738b5 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1,6 +1,6 @@
 %% ipc.tex
 %%
-%% Copyright (C) 2000-2002 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2004 Simone Piccardi.  Permission is granted to
 %% copy, distribute and/or modify this document under the terms of the GNU Free
 %% Documentation License, Version 1.1 or any later version published by the
 %% Free Software Foundation; with the Invariant Sections being "Prefazione",
@@ -41,7 +41,7 @@ ne gestiscono l'uso e le varie forme in cui si 
 
 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 una una coppia di file descriptor\footnote{si tenga presente che
+sostanza di 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
@@ -67,8 +67,8 @@ scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale
 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 dal parametro di sistema \const{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
+sez.~\ref{sec:sys_file_limits}). Lo schema di funzionamento di una pipe è
+illustrato in fig.~\ref{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.
 
@@ -80,12 +80,12 @@ indicano la direzione del flusso dei dati.
 \end{figure}
 
 Chiaramente creare una pipe all'interno di un singolo processo non serve a
-niente; se però ricordiamo quanto esposto in \secref{sec:file_sharing}
+niente; se però ricordiamo quanto esposto in sez.~\ref{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
+fig.~\ref{fig:ipc_pipe_fork}). In questo modo se uno dei processi scrive su un
 capo della pipe, l'altro può leggere.
 
 \begin{figure}[htb]
@@ -112,7 +112,7 @@ 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 \errcode{EPIPE}, e la funzione di scrittura
+processo riceverà il segnale \const{SIGPIPE}, e la funzione di scrittura
 restituirà un errore di \errcode{EPIPE} (al ritorno del gestore, o qualora il
 segnale sia ignorato o bloccato).
 
@@ -154,15 +154,15 @@ Per realizzare quanto voluto useremo in sequenza i programmi \cmd{barcode} e
 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
+secondo, secondo lo schema mostrato in fig.~\ref{fig:ipc_pipe_use}, in cui la
 direzione del flusso dei dati è data dalle frecce continue.
 
 \begin{figure}[htb]
   \centering
   \includegraphics[height=5cm]{img/pipeuse}
   \caption{Schema dell'uso di una pipe come mezzo di comunicazione fra
-    due processi attraverso attraverso l'esecuzione una \func{fork} e la
-    chiusura dei capi non utilizzati.}
+    due processi attraverso l'esecuzione una \func{fork} e la chiusura dei
+    capi non utilizzati.}
   \label{fig:ipc_pipe_use}
 \end{figure}
 
@@ -179,66 +179,19 @@ essere molto pi
 
 Il programma ci servirà anche come esempio dell'uso delle funzioni di
 duplicazione dei file descriptor che abbiamo trattato in
-\secref{sec:file_dup}, in particolare di \func{dup2}. È attraverso queste
+sez.~\ref{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_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.
+(che abbiamo visto in sez.~\ref{sec:file_std_descr} e
+sez.~\ref{sec:file_std_stream}) sulla pipe. In
+fig.~\ref{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.
 
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[], char *envp[])
-{
-    ...
-    /* create two pipes, pipein and pipeout, to handle 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);
-    } 
-    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) {
-        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}
+    \includecodesample{listati/BarCodePage.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del \textit{CGI} 
@@ -251,7 +204,7 @@ 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_barcodepage_code}; essa si incarica semplicemente di
+  fig.~\ref{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.}
@@ -348,11 +301,11 @@ 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
-stream visti in \capref{cha:files_std_interface}, anche se è collegato ad una
-pipe e non ad un file, e viene sempre aperto in modalità
-\textit{fully-buffered} (vedi \secref{sec:file_buffering}); l'unica differenza
-con gli usuali stream è che dovrà essere chiuso dalla seconda delle due nuove
-funzioni, \funcd{pclose}, il cui prototipo è:
+stream visti in cap.~\ref{cha:files_std_interface}, anche se è collegato ad
+una pipe e non ad un file, e viene sempre aperto in modalità
+\textit{fully-buffered} (vedi sez.~\ref{sec:file_buffering}); l'unica
+differenza con gli usuali stream è che dovrà essere chiuso dalla seconda delle
+due nuove funzioni, \funcd{pclose}, il cui prototipo è:
 \begin{prototype}{stdio.h}
 {int pclose(FILE *stream)}
 
@@ -368,7 +321,7 @@ 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_barcodepage_code} per
+precedente: il programma mostrato in fig.~\ref{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
@@ -412,48 +365,18 @@ 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_barcode_code}.  Come si può notare l'ordine di invocazione dei
-programmi è l'inverso di quello in cui ci si aspetta che vengano
+fig.~\ref{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 precedente, benchè quest'ultimo venga
-invocato dopo.
+risultato dell'elaborazione del precedente, benchè quest'ultimo venga invocato
+dopo.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[], char *envp[])
-{
-    FILE *pipe[4];
-    FILE *pipein;
-    char *cmd_string[4]={
-        "pnmtopng",
-        "pnmmargin -white 10",
-        "pnmcrop",
-        "gs -sDEVICE=ppmraw -sOutputFile=- -sNOPAUSE -q - -c showpage -c quit"
-    };  
-    char content[]="Content-type: image/png\n\n";
-    int i;
-    /* write mime-type to stdout */ 
-    write(STDOUT_FILENO, content, strlen(content));
-    /* execute chain of command */
-    for (i=0; i<4; i++) {
-        pipe[i] = popen(cmd_string[i], "w");
-        dup2(fileno(pipe[i]), STDOUT_FILENO); 
-    }
-    /* create barcode (in PS) */
-    pipein = popen("barcode", "w");
-    /* send barcode string to barcode program */
-    write(fileno(pipein), argv[1], strlen(argv[1]));
-    /* close all pipes (in reverse order) */
-    for (i=4; i==0; i--) {
-        pclose((pipe[i]));
-    }
-    exit(0);
-}
-    \end{lstlisting}
+    \includecodesample{listati/BarCode.c}
   \end{minipage} 
   \normalsize 
   \caption{Codice completo del \textit{CGI} \file{BarCode.c}.}
@@ -487,10 +410,10 @@ create, tutte le pipe create con \func{pclose}.
 \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
+Come accennato in sez.~\ref{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 che invece di essere strutture interne del
 kernel, visibili solo attraverso un file descriptor, sono accessibili
 attraverso un inode\index{inode} che risiede sul filesystem, così che i
@@ -502,9 +425,9 @@ attraverso un apposito buffer nel kernel, senza transitare dal filesystem;
 l'inode\index{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}.
+quello illustrato per le pipe in sez.~\ref{sec:ipc_pipes}.
 
-Abbiamo già visto in \secref{sec:file_mknod} le funzioni \func{mknod} e
+Abbiamo già visto in sez.~\ref{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à
@@ -538,7 +461,7 @@ 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 \const{PIPE\_BUF} (si ricordi quanto detto in
-\secref{sec:ipc_pipes}).
+sez.~\ref{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:
@@ -548,7 +471,7 @@ riporta in \cite{APUE} altre due casistiche principali per l'uso delle fifo:
   sull'input di parecchi altri (attraverso l'uso del comando \cmd{tee}).
   
 \item Come canale di comunicazione fra client ed server (il modello
-  \textit{client-server} è illustrato in \secref{sec:net_cliserv}).
+  \textit{client-server} è illustrato in sez.~\ref{sec:net_cliserv}).
 \end{itemize}
 
 Nel primo caso quello che si fa è creare tante fifo, da usare come standard
@@ -567,7 +490,7 @@ 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 in \figref{fig:ipc_fifo_server_arch} in cui i client inviano le
+illustrata in fig.~\ref{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'occasione.
 
@@ -584,7 +507,7 @@ 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
+fig.~\ref{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
@@ -594,60 +517,7 @@ diverso da quelli preimpostati. Il codice completo 
 \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/linux";
-    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);
-        }
-    }
-    daemon(0, 0);
-    /* 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}
+    \includecodesample{listati/FortuneServer.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del server di \textit{fortunes}
@@ -661,8 +531,8 @@ dell'insieme delle frasi non nulla, dato che l'inizializzazione del vettore
 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.
+(anche questa non è riportata in fig.~\ref{fig:ipc_fifo_server}) che si limita
+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
@@ -728,53 +598,16 @@ all'apertura della fifo per la risposta, che poi \texttt{\small 47--48}) 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
+Il codice del client è invece riportato in fig.~\ref{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}
+    \includecodesample{listati/FortuneClient.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del client di \textit{fortunes}
@@ -826,7 +659,7 @@ leggere una decina di frasi, con:
 Avendo usato \func{daemon} per eseguire il server in background il comando
 ritornerà immediatamente, ma potremo verificare con \cmd{ps} che in effetti il
 programma resta un esecuzione in background, e senza avere associato un
-terminale di controllo (si ricordi quanto detto in \secref{sec:sess_daemon}):
+terminale di controllo (si ricordi quanto detto in sez.~\ref{sec:sess_daemon}):
 \begin{verbatim}
 [piccardi@gont sources]$ ps aux
 ...
@@ -874,8 +707,8 @@ complessa e continua ad avere vari inconvenienti\footnote{lo stesso Stevens,
 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.
+cap.~\ref{cha:socket_intro}) o ricorrendo a meccanismi di comunicazione
+diversi, come quelli che esamineremo in seguito.
 
 
 
@@ -885,12 +718,12 @@ come quelli che esamineremo in seguito.
 Un meccanismo di comunicazione molto simile alle pipe, ma che non presenta il
 problema della unidirezionalità del flusso dei dati, è quello dei cosiddetti
 \textsl{socket locali} (o \textit{Unix domain socket}). Tratteremo l'argomento
-dei \textit{socket}\index{socket} in \capref{cha:socket_intro},\footnote{si
+dei \textit{socket}\index{socket} in cap.~\ref{cha:socket_intro},\footnote{si
   tratta comunque di oggetti di comunicazione che, come le pipe, sono
   utilizzati attraverso dei file descriptor.} nell'ambito dell'interfaccia
 generale che essi forniscono per la programmazione di rete; e vedremo anche
-(in~\secref{sec:sock_sa_local}) come si possono definire dei file speciali (di
-tipo \textit{socket}, analoghi a quello associati alle fifo) cui si accede
+(in~sez.~\ref{sec:sock_sa_local}) come si possono definire dei file speciali
+(di tipo \textit{socket}, analoghi a quello associati alle fifo) cui si accede
 però attraverso quella medesima interfaccia; vale però la pena esaminare qui
 una modalità di uso dei socket locali\footnote{la funzione \func{socketpair} è
   stata introdotta in BSD4.4, ma è supportata in genere da qualunque sistema
@@ -938,10 +771,10 @@ socket\index{socket} locali in generale) permette di trasmettere attraverso le
 linea non solo dei dati, ma anche dei file descriptor: si può cioè passare da
 un processo ad un altro un file descriptor, con una sorta di duplicazione
 dello stesso non all'interno di uno stesso processo, ma fra processi distinti
-(torneremo su questa funzionalità in \secref{sec:xxx_fd_passing}).
+(torneremo su questa funzionalità in sez.~\ref{sec:xxx_fd_passing}).
 
 
-\section{La comunicazione fra processi di System V}
+\section{Il sistema di comunicazione fra processi di System V}
 \label{sec:ipc_sysv}
 
 Benché le pipe e le fifo siano ancora ampiamente usate, esse scontano il
@@ -953,7 +786,7 @@ 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 chiamato il
-\textsl{Sistema di comunicazione inter-processo} di System V, cui da qui in
+\textsl{Sistema di comunicazione fra processi} di System V, cui da qui in
 avanti faremo riferimento come \textit{SysV IPC} (dove IPC è la sigla di
 \textit{Inter-Process Comunication}).
 
@@ -981,7 +814,7 @@ Un'ulteriore caratteristica negativa 
 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
+torneremo in sez.~\ref{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à, né utilizzare un qualche valore statico,
@@ -996,24 +829,13 @@ tramite la quale 
   si sposta il problema dell'accesso dalla classificazione in base
   all'identificatore alla classificazione in base alla chiave, una delle tante
   complicazioni inutili presenti nel \textit{SysV IPC}.} Oltre la chiave, la
-struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm},
+struttura, la cui definizione è riportata in fig.~\ref{fig:ipc_ipc_perm},
 mantiene varie proprietà ed informazioni 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}
+    \includestruct{listati/ipc_perm.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{ipc\_perm}, come definita in
@@ -1089,7 +911,7 @@ problema del \textit{SysV IPC}. Non esiste infatti una modalit
 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}.
+sez.~\ref{sec:ipc_posix}.
 
 
 \subsection{Il controllo di accesso}
@@ -1100,7 +922,7 @@ Oltre alle chiavi, abbiamo visto che ad ogni oggetto sono associate in
 (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}).
+simile a quello che si ha per i file (vedi sez.~\ref{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
@@ -1108,7 +930,7 @@ esiste (e se specificato viene ignorato), per cui si pu
 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
+tab.~\ref{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 \const{MSG\_R} (\texttt{0400}) e
   \const{MSG\_W} (\texttt{0200}) per indicare i permessi base di lettura e
@@ -1154,14 +976,14 @@ 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.
+sez.~\ref{sec:file_umask}) non ha alcun significato.
 
 
 \subsection{Gli identificatori ed il loro utilizzo}
 \label{sec:ipc_sysv_id_use}
 
 L'unico campo di \struct{ipc\_perm} del quale non abbiamo ancora parlato è
-\var{seq}, che in \figref{fig:ipc_ipc_perm} è qualificato con un criptico
+\var{seq}, che in fig.~\ref{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.
@@ -1210,41 +1032,7 @@ s
 \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}
+    \includecodesample{listati/IPCTestId.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del programma di test per l'assegnazione degli
@@ -1252,12 +1040,12 @@ int main(int argc, char *argv[])
   \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.
+In fig.~\ref{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
@@ -1346,7 +1134,7 @@ 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 \const{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}.
+oggetto, secondo quanto illustrato in sez.~\ref{sec:ipc_sysv_access_control}.
 Se si imposta anche il bit corrispondente a \const{IPC\_EXCL} la funzione avrà
 successo solo se l'oggetto non esiste già, fallendo con un errore di
 \errcode{EEXIST} altrimenti.
@@ -1383,7 +1171,7 @@ coda.
 
 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
+tab.~\ref{tab:ipc_msg_limits}, come accennato però in Linux è possibile
 modificare questi limiti attraverso l'uso di \func{sysctl} o scrivendo nei
 file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}.
 
@@ -1403,9 +1191,9 @@ Una coda di messaggi 
   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 \figref{fig:ipc_mq_schema} è in
+coda alla lista e vengono letti dalla cima, in fig.~\ref{fig:ipc_mq_schema} si
+è riportato lo schema con cui queste strutture vengono mantenute dal
+kernel.\footnote{lo schema illustrato in fig.~\ref{fig:ipc_mq_schema} è in
   realtà una semplificazione di quello usato effettivamente fino ai kernel
   della serie 2.2.x, nei kernel della serie 2.4.x la gestione delle code di
   messaggi è stata modificata ed è effettuata in maniera diversa; abbiamo
@@ -1415,21 +1203,7 @@ kernel.\footnote{lo schema illustrato in \figref{fig:ipc_mq_schema} 
 \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 */
-    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 */
-    unsigned long int msg_cbytes; /* current number of bytes on queue */
-};
-    \end{lstlisting}
+    \includestruct{listati/msqid_ds.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{msqid\_ds}, associata a ciascuna coda di
@@ -1438,24 +1212,24 @@ struct msqid_ds {
 \end{figure}
 
 A ciascuna coda è associata una struttura \struct{msgid\_ds}, la cui
-definizione, è riportata in \secref{fig:ipc_msqid_ds}. In questa struttura il
+definizione, è riportata in fig.~\ref{fig:ipc_msqid_ds}. In questa struttura il
 kernel mantiene le principali informazioni riguardo lo stato corrente della
 coda.\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.  Si noti come ci
   sia una differenza con i campi mostrati nello schema di
-  \figref{fig:ipc_mq_schema} che sono presi dalla definizione di
+  fig.~\ref{fig:ipc_mq_schema} che sono presi dalla definizione di
   \file{linux/msg.h}, e fanno riferimento alla definizione della omonima
-  struttura usata nel kernel.} In \figref{fig:ipc_msqid_ds} sono elencati i
+  struttura usata nel kernel.} In fig.~\ref{fig:ipc_msqid_ds} sono elencati i
 campi significativi definiti in \file{sys/msg.h}, a cui si sono aggiunti gli
 ultimi tre campi che sono previsti dalla implementazione originale di System
 V, ma non dallo standard Unix98.
 
 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
+come illustrato in sez.~\ref{sec:ipc_sysv_access_control}, per quanto riguarda
 gli altri campi invece:
-\begin{itemize}
+\begin{itemize*}
 \item il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti
   sulla coda, viene inizializzato a 0.
 \item i campi \var{msg\_lspid} e \var{msg\_lrpid}, che esprimono
@@ -1474,7 +1248,7 @@ gli altri campi invece:
   \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
   inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
   e non devono essere utilizzati da programmi in user space).
-\end{itemize}
+\end{itemize*}
 
 Una volta creata una coda di messaggi le operazioni di controllo vengono
 effettuate con la funzione \funcd{msgctl}, che (come le analoghe \func{semctl}
@@ -1516,7 +1290,7 @@ eseguire; i valori possibili sono:
 \item[\const{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 \errcode{EIDRM}, e tutti processi in attesa su
-  funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo
+  funzioni di lettura o di scrittura sulla coda saranno svegliati ricevendo
   il medesimo errore. Questo comando può essere eseguito solo da un processo
   con user-ID effettivo corrispondente al creatore o al proprietario della
   coda, o all'amministratore.
@@ -1565,11 +1339,11 @@ La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
 messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso il
 l'argomento \param{msgp}.  Quest'ultimo deve venire passato sempre come
 puntatore ad una struttura \struct{msgbuf} analoga a quella riportata in
-\figref{fig:ipc_msbuf} che è quella che deve contenere effettivamente il
+fig.~\ref{fig:ipc_msbuf} che è quella che deve contenere effettivamente il
 messaggio.  La dimensione massima per il testo di un messaggio non può
 comunque superare il limite \const{MSGMAX}.
 
-La struttura di \figref{fig:ipc_msbuf} è comunque solo un modello, tanto che
+La struttura di fig.~\ref{fig:ipc_msbuf} è comunque solo un modello, tanto che
 la definizione contenuta in \file{sys/msg.h} usa esplicitamente per il secondo
 campo il valore \code{mtext[1]}, che non è di nessuna utilità ai fini pratici.
 La sola cosa che conta è che la struttura abbia come primo membro un campo
@@ -1579,7 +1353,7 @@ messaggio e deve essere sempre specificato come intero positivo di tipo
 dimensione, e serve a contenere il testo del messaggio.
 
 In generale pertanto per inviare un messaggio con \func{msgsnd} si usa
-ridefinire una struttura simile a quella di \figref{fig:ipc_msbuf}, adattando
+ridefinire una struttura simile a quella di fig.~\ref{fig:ipc_msbuf}, adattando
 alle proprie esigenze il campo \var{mtype}, (o ridefinendo come si vuole il
 corpo del messaggio, anche con più campi o con strutture più complesse) avendo
 però la cura di mantenere nel primo campo un valore di tipo \ctyp{long} che ne
@@ -1589,18 +1363,13 @@ Si tenga presente che la lunghezza che deve essere indicata in questo
 argomento è solo quella del messaggio, non quella di tutta la struttura, se
 cioè \var{message} è una propria struttura che si passa alla funzione,
 \param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se
-consideriamo il caso dell'esempio in \figref{fig:ipc_msbuf}, \param{msgsz}
+consideriamo il caso dell'esempio in fig.~\ref{fig:ipc_msbuf}, \param{msgsz}
 dovrà essere pari a \const{LENGTH}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-    struct msgbuf {
-         long mtype;          /* message type, must be > 0 */
-         char mtext[LENGTH];  /* message data */
-    };
-    \end{lstlisting}
+    \includestruct{listati/msgbuf.h}
   \end{minipage} 
   \normalsize 
   \caption{Schema della struttura \structd{msgbuf}, da utilizzare come
@@ -1610,7 +1379,7 @@ dovr
 
 Per capire meglio il funzionamento della funzione riprendiamo in
 considerazione la struttura della coda illustrata in
-\figref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
+fig.~\ref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
 sarà aggiunto in fondo alla lista inserendo una nuova struttura \struct{msg},
 il puntatore \var{msg\_last} di \struct{msqid\_ds} verrà aggiornato, come pure
 il puntatore al messaggio successivo per quello che era il precedente ultimo
@@ -1675,10 +1444,10 @@ La funzione che viene utilizzata per estrarre un messaggio da una coda 
 
 La funzione legge un messaggio dalla coda specificata, scrivendolo sulla
 struttura puntata da \param{msgp}, che dovrà avere un formato analogo a quello
-di \figref{fig:ipc_msbuf}.  Una volta estratto, il messaggio sarà rimosso dalla
-coda.  L'argomento \param{msgsz} indica la lunghezza massima del testo del
-messaggio (equivalente al valore del parametro \const{LENGTH} nell'esempio di
-\figref{fig:ipc_msbuf}).
+di fig.~\ref{fig:ipc_msbuf}.  Una volta estratto, il messaggio sarà rimosso
+dalla coda.  L'argomento \param{msgsz} indica la lunghezza massima del testo
+del messaggio (equivalente al valore del parametro \const{LENGTH} nell'esempio
+di fig.~\ref{fig:ipc_msbuf}).
 
 Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene
 rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a
@@ -1688,13 +1457,13 @@ un errore di \errcode{E2BIG}.
 
 L'argomento \param{msgtyp} permette di restringere la ricerca ad un
 sottoinsieme dei messaggi presenti sulla coda; la ricerca infatti è fatta con
-una scansione della struttura mostrata in \figref{fig:ipc_mq_schema},
+una scansione della struttura mostrata in fig.~\ref{fig:ipc_mq_schema},
 restituendo il primo messaggio incontrato che corrisponde ai criteri
 specificati (che quindi, visto come i messaggi vengono sempre inseriti dalla
 coda, è quello meno recente); in particolare:
 \begin{itemize}
 \item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè
-  quello fra i presenti che è stato inserito inserito per primo. 
+  quello fra i presenti che è stato inserito per primo. 
 \item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui
   tipo (il valore del campo \var{mtype}) corrisponde al valore di
   \param{msgtyp}.
@@ -1737,10 +1506,10 @@ tutte le risorse occupate vengono rilasciate quanto l'ultimo processo che le
 utilizzava termina. Questo comporta che in caso di errori si può saturare il
 sistema, e che devono comunque essere esplicitamente previste delle funzioni
 di rimozione in caso di interruzioni o uscite dal programma (come vedremo in
-\figref{fig:ipc_mq_fortune_server}).
+fig.~\ref{fig:ipc_mq_fortune_server}).
 
 L'altro problema è non facendo uso di file descriptor le tecniche di
-\textit{I/O multiplexing} descritte in \secref{sec:file_multiplexing} non
+\textit{I/O multiplexing} descritte in sez.~\ref{sec:file_multiplexing} non
 possono essere utilizzate, e non si ha a disposizione niente di analogo alle
 funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di
 una di queste strutture alla volta; ad esempio non si può scrivere un server
@@ -1755,57 +1524,8 @@ in maniera indipendente con client diversi.
 
 \begin{figure}[!bht]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int msgid;                                       /* Message queue identifier */
-int main(int argc, char *argv[])
-{
-/* Variables definition */
-    int i, n = 0;
-    char **fortune;                       /* array of fortune message string */
-    char *fortunefilename = "/usr/share/games/fortunes/linux";  /* file name */
-    struct msgbuf_read {      /* message struct to read request from clients */
-        long mtype;                               /* message type, must be 1 */
-        long pid;             /* message data, must be the pid of the client */
-    } msg_read;
-    struct msgbuf_write {       /* message struct to write result to clients */
-        long mtype;            /* message type, will be the pid of the client*/
-        char mtext[MSGMAX];             /* message data, will be the fortune */
-    } msg_write;
-    key_t key;                                          /* Message queue key */
-    int size;                                                /* message size */
-    ...
-    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
-    Signal(SIGINT, HandSIGTERM);
-    Signal(SIGQUIT, HandSIGTERM);
-    if (n==0) usage();          /* if no pool depth exit printing usage info */
-    i = FortuneParse(fortunefilename, fortune, n);          /* parse phrases */
-    /* Create the queue */
-    key = ftok("./MQFortuneServer.c", 1); 
-    msgid = msgget(key, IPC_CREAT|0666);
-    if (msgid < 0) {
-        perror("Cannot create message queue");
-        exit(1);
-    }
-    /* Main body: loop over requests */
-    daemon(0, 0);
-    while (1) {
-        msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR);
-        n = random() % i;                             /* select random value */
-        strncpy(msg_write.mtext, fortune[n], MSGMAX);
-        size = min(strlen(fortune[n])+1, MSGMAX);  
-        msg_write.mtype=msg_read.pid;             /* use request pid as type */
-        msgsnd(msgid, &msg_write, size, 0);
-    }
-}
-/*
- * Signal Handler to manage termination
- */
-void HandSIGTERM(int signo) {
-    msgctl(msgid, IPC_RMID, NULL);                   /* remove message queue */
-    exit(0);
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MQFortuneServer.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del server di \textit{fortunes}
@@ -1813,7 +1533,7 @@ void HandSIGTERM(int signo) {
   \label{fig:ipc_mq_fortune_server}
 \end{figure}
 
-In \figref{fig:ipc_mq_fortune_server} si è riportato un estratto delle parti
+In fig.~\ref{fig:ipc_mq_fortune_server} si è riportato un estratto delle parti
 principali del codice del nuovo server (il codice completo è nel file
 \file{MQFortuneServer.c} nei sorgenti allegati). Il programma è basato su un
 uso accorto della caratteristica di poter associate un ``tipo'' ai messaggi
@@ -1878,26 +1598,8 @@ gestore \code{HandSIGTERM}, che semplicemente si limita a cancellare la coda
 
 \begin{figure}[!bht]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[])
-{
-    ...
-    key = ftok("./MQFortuneServer.c", 1); 
-    msgid = msgget(key, 0); 
-    if (msgid < 0) {
-        perror("Cannot find message queue");
-        exit(1);
-    }
-    /* Main body: do request and write result */
-    msg_read.mtype = 1;                      /* type for request is always 1 */
-    msg_read.pid = getpid();                   /* use pid for communications */
-    size = sizeof(msg_read.pid);  
-    msgsnd(msgid, &msg_read, size, 0);               /* send request message */
-    msgrcv(msgid, &msg_write, MSGMAX, msg_read.pid, MSG_NOERROR);
-    printf("%s", msg_write.mtext);
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MQFortuneClient.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del client di \textit{fortunes}
@@ -1905,13 +1607,13 @@ int main(int argc, char *argv[])
   \label{fig:ipc_mq_fortune_client}
 \end{figure}
 
-In \figref{fig:ipc_mq_fortune_client} si è riportato un estratto il codice del
-programma client.  Al solito il codice completo è con i sorgenti allegati, nel
-file \file{MQFortuneClient.c}.  Come sempre si sono rimosse le parti relative
-alla gestione delle opzioni, ed in questo caso, anche la dichiarazione delle
-variabili, che, per la parte relative alle strutture usate per la
-comunicazione tramite le code, sono le stesse viste in
-\figref{fig:ipc_mq_fortune_server}.
+In fig.~\ref{fig:ipc_mq_fortune_client} si è riportato un estratto il codice
+del programma client.  Al solito il codice completo è con i sorgenti allegati,
+nel file \file{MQFortuneClient.c}.  Come sempre si sono rimosse le parti
+relative alla gestione delle opzioni, ed in questo caso, anche la
+dichiarazione delle variabili, che, per la parte relative alle strutture usate
+per la comunicazione tramite le code, sono le stesse viste in
+fig.~\ref{fig:ipc_mq_fortune_server}.
 
 Il client in questo caso è molto semplice; la prima parte del programma
 (\texttt{\small 4--9}) si occupa di accedere alla coda di messaggi, ed è
@@ -1989,7 +1691,7 @@ I semafori non sono meccanismi di intercomunicazione diretta come quelli
 (pipe, fifo e code di messaggi) visti finora, e non consentono di scambiare
 dati fra processi, ma servono piuttosto come meccanismi di sincronizzazione o
 di protezione per le \textsl{sezioni critiche}\index{sezioni critiche} del
-codice (si ricordi quanto detto in \secref{sec:proc_race_cond}). 
+codice (si ricordi quanto detto in sez.~\ref{sec:proc_race_cond}). 
 
 Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a
 seconda del suo valore, di consentire o meno la prosecuzione dell'esecuzione
@@ -2058,7 +1760,7 @@ permette di creare o ottenere l'identificatore di un insieme di semafori 
 La funzione è del tutto analoga a \func{msgget}, solo che in questo caso
 restituisce l'identificatore di un insieme di semafori, in particolare è
 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
+ripeteremo quanto detto al proposito in sez.~\ref{sec:ipc_sysv_mq}. L'argomento
 \param{nsems} permette di specificare quanti semafori deve contenere l'insieme
 quando se ne richieda la creazione, e deve essere nullo quando si effettua una
 richiesta dell'identificatore di un insieme già esistente.
@@ -2087,15 +1789,7 @@ semaforo all'uscita del processo.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct semid_ds
-{
-    struct ipc_perm sem_perm;           /* operation permission struct */
-    time_t sem_otime;                   /* last semop() time */
-    time_t sem_ctime;                   /* last time changed by semctl() */
-    unsigned long int sem_nsems;        /* number of semaphores in set */
-};
-    \end{lstlisting}
+    \includestruct{listati/semid_ds.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{semid\_ds}, associata a ciascun insieme di
@@ -2104,14 +1798,15 @@ struct semid_ds
 \end{figure}
 
 A ciascun insieme di semafori è associata una struttura \struct{semid\_ds},
-riportata in \figref{fig:ipc_semid_ds}.\footnote{non si sono riportati i campi
-  ad uso interno del kernel, che vedremo in \figref{fig:ipc_sem_schema}, che
-  dipendono dall'implementazione.} Come nel caso delle code di messaggi quando
-si crea un nuovo insieme di semafori con \func{semget} questa struttura viene
-inizializzata, in particolare il campo \var{sem\_perm} viene inizializzato
-come illustrato in \secref{sec:ipc_sysv_access_control} (si ricordi che in
-questo caso il permesso di scrittura è in realtà permesso di alterare il
-semaforo), per quanto riguarda gli altri campi invece:
+riportata in fig.~\ref{fig:ipc_semid_ds}.\footnote{non si sono riportati i
+  campi ad uso interno del kernel, che vedremo in
+  fig.~\ref{fig:ipc_sem_schema}, che dipendono dall'implementazione.} Come nel
+caso delle code di messaggi quando si crea un nuovo insieme di semafori con
+\func{semget} questa struttura viene inizializzata, in particolare il campo
+\var{sem\_perm} viene inizializzato come illustrato in
+sez.~\ref{sec:ipc_sysv_access_control} (si ricordi che in questo caso il
+permesso di scrittura è in realtà permesso di alterare il semaforo), per
+quanto riguarda gli altri campi invece:
 \begin{itemize*}
 \item il campo \var{sem\_nsems}, che esprime il numero di semafori
   nell'insieme, viene inizializzato al valore di \param{nsems}.
@@ -2129,22 +1824,15 @@ Ciascun semaforo dell'insieme 
   ormai è ridotta ai soli due primi membri, e gli altri vengono calcolati
   dinamicamente. La si è utilizzata a scopo di esempio, perché indica tutti i
   valori associati ad un semaforo, restituiti dalle funzioni di controllo, e
-  citati dalle pagine di manuale.} è riportata in \figref{fig:ipc_sem}. Questa
-struttura, non è accessibile in user space, ma i valori in essa specificati
-possono essere letti in maniera indiretta, attraverso l'uso delle funzioni di
-controllo.
+  citati dalle pagine di manuale.} è riportata in fig.~\ref{fig:ipc_sem}.
+Questa struttura, non è accessibile in user space, ma i valori in essa
+specificati possono essere letti in maniera indiretta, attraverso l'uso delle
+funzioni di controllo.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct sem {
-  short   sempid;         /* pid of last operation */
-  ushort  semval;         /* current value */
-  ushort  semncnt;        /* num procs awaiting increase in semval */
-  ushort  semzcnt;        /* num procs awaiting semval = 0 */
-};
-    \end{lstlisting}
+    \includestruct{listati/sem.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{sem}, che contiene i dati di un singolo
@@ -2152,7 +1840,7 @@ struct sem {
   \label{fig:ipc_sem}
 \end{figure}
 
-I dati mantenuti nella struttura, ed elencati in \figref{fig:ipc_sem},
+I dati mantenuti nella struttura, ed elencati in fig.~\ref{fig:ipc_sem},
 indicano rispettivamente:
 \begin{description*}
 \item[\var{semval}] il valore numerico del semaforo.
@@ -2191,8 +1879,8 @@ indicano rispettivamente:
 
 Come per le code di messaggi anche per gli insiemi di semafori esistono una
 serie di limiti, i cui valori sono associati ad altrettante costanti, che si
-sono riportate in \tabref{tab:ipc_sem_limits}. Alcuni di questi limiti sono al
-solito accessibili e modificabili attraverso \func{sysctl} o scrivendo
+sono riportate in tab.~\ref{tab:ipc_sem_limits}. Alcuni di questi limiti sono
+al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo
 direttamente nel file \file{/proc/sys/kernel/sem}.
 
 La funzione che permette di effettuare le varie operazioni di controllo sui
@@ -2234,15 +1922,7 @@ specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-union semun {
-      int val;                  /* value for SETVAL */
-      struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
-      unsigned short *array;    /* array for GETALL, SETALL */
-                                /* Linux specific part: */
-      struct seminfo *__buf;    /* buffer for IPC_INFO */
-};
-    \end{lstlisting}
+    \includestruct{listati/semun.h}
   \end{minipage} 
   \normalsize 
   \caption{La definizione dei possibili valori di una \direct{union}
@@ -2255,7 +1935,7 @@ Qualora la funzione operi con quattro argomenti \param{arg} 
 generico, che conterrà un dato diverso a seconda dell'azione richiesta; per
 unificare l'argomento esso deve essere passato come una \struct{semun}, la cui
 definizione, con i possibili valori che può assumere, è riportata in
-\figref{fig:ipc_semun}.
+fig.~\ref{fig:ipc_semun}.
 
 Come già accennato sia il comportamento della funzione che il numero di
 parametri con cui deve essere invocata, dipendono dal valore dell'argomento
@@ -2340,7 +2020,7 @@ tutti i semafori il cui valore viene modificato.
 Il valore di ritorno della funzione in caso di successo dipende
 dall'operazione richiesta; per tutte le operazioni che richiedono quattro
 argomenti esso è sempre nullo, per le altre operazioni, elencate in
-\tabref{tab:ipc_semctl_returns} viene invece restituito il valore richiesto,
+tab.~\ref{tab:ipc_semctl_returns} viene invece restituito il valore richiesto,
 corrispondente al campo della struttura \struct{sem} indicato nella seconda
 colonna della tabella.
 
@@ -2388,14 +2068,7 @@ effettivamente eseguite se e soltanto se 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct sembuf
-{
-  unsigned short int sem_num;   /* semaphore number */
-  short int sem_op;             /* semaphore operation */
-  short int sem_flg;            /* operation flag */
-};
-    \end{lstlisting}
+    \includestruct{listati/sembuf.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{sembuf}, usata per le operazioni sui
@@ -2405,7 +2078,7 @@ struct sembuf
 
 Il contenuto di ciascuna operazione deve essere specificato attraverso una
 opportuna struttura \struct{sembuf} (la cui definizione è riportata in
-\figref{fig:ipc_sembuf}) che il programma chiamante deve avere cura di
+fig.~\ref{fig:ipc_sembuf}) che il programma chiamante deve avere cura di
 allocare in un opportuno vettore. La struttura permette di indicare il
 semaforo su cui operare, il tipo di operazione, ed un flag di controllo.
 Il campo \var{sem\_num} serve per indicare a quale semaforo dell'insieme fa
@@ -2496,7 +2169,7 @@ una \func{exec} (altrimenti non si avrebbe ripristino).
 
 Tutto questo però ha un problema di fondo. Per capire di cosa si tratta
 occorre fare riferimento all'implementazione usata in Linux, che è riportata
-in maniera semplificata nello schema di \figref{fig:ipc_sem_schema}.  Si è
+in maniera semplificata nello schema di fig.~\ref{fig:ipc_sem_schema}.  Si è
 presa come riferimento l'architettura usata fino al kernel 2.2.x che è più
 semplice (ed illustrata in dettaglio in \cite{tlk}); nel kernel 2.4.x la
 struttura del \textit{SysV IPC} è stata modificata, ma le definizioni relative
@@ -2563,7 +2236,7 @@ ripristino non 
 Come esempio di uso dell'interfaccia dei semafori vediamo come implementare
 con essa dei semplici \textit{mutex} (cioè semafori binari), tutto il codice
 in questione, contenuto nel file \file{Mutex.c} allegato ai sorgenti, è
-riportato in \figref{fig:ipc_mutex_create}. Utilizzeremo l'interfaccia per
+riportato in fig.~\ref{fig:ipc_mutex_create}. Utilizzeremo l'interfaccia per
 creare un insieme contenente un singolo semaforo, per il quale poi useremo un
 valore unitario per segnalare la disponibilità della risorsa, ed un valore
 nullo per segnalarne l'indisponibilità. 
@@ -2571,57 +2244,7 @@ nullo per segnalarne l'indisponibilit
 \begin{figure}[!bht]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/* Function MutexCreate: create a mutex/semaphore */
-int MutexCreate(key_t ipc_key) 
-{
-    const union semun semunion={1};             /* semaphore union structure */
-    int sem_id, ret;
-    sem_id = semget(ipc_key, 1, IPC_CREAT|0666);         /* get semaphore ID */
-    if (sem_id == -1) {                              /* if error return code */
-        return sem_id;
-    }
-    ret = semctl(sem_id, 0, SETVAL, semunion);             /* init semaphore */
-    if (ret == -1) {
-        return ret;
-    }
-    return sem_id;
-}
-/* Function MutexFind: get the semaphore/mutex Id given the IPC key value */
-int MutexFind(key_t ipc_key) 
-{
-    return semget(ipc_key,1,0);
-}
-/* Function MutexRead: read the current value of the mutex/semaphore */
-int MutexRead(int sem_id) 
-{
-    return semctl(sem_id, 0, GETVAL);
-}
-/* Define sembuf structures to lock and unlock the semaphore  */
-struct sembuf sem_lock={                                /* to lock semaphore */
-    0,                                   /* semaphore number (only one so 0) */
-    -1,                                    /* operation (-1 to use resource) */
-    SEM_UNDO};                                /* flag (set for undo at exit) */
-struct sembuf sem_ulock={                             /* to unlock semaphore */
-    0,                                   /* semaphore number (only one so 0) */
-    1,                                  /* operation (1 to release resource) */
-    SEM_UNDO};                                      /* flag (in this case 0) */
-/* Function MutexLock: to lock a mutex/semaphore */
-int MutexLock(int sem_id) 
-{
-    return semop(sem_id, &sem_lock, 1);
-}
-/* Function MutexUnlock: to unlock a mutex/semaphore */
-int MutexUnlock(int sem_id) 
-{
-    return semop(sem_id, &sem_ulock, 1);
-}
-/* Function MutexRemove: remove a mutex/semaphore */
-int MutexRemove(int sem_id) 
-{
-    return semctl(sem_id, 0, IPC_RMID);
-}
-    \end{lstlisting}
+    \includecodesample{listati/Mutex.c}
   \end{minipage} 
   \normalsize 
   \caption{Il codice delle funzioni che permettono di creare o recuperare
@@ -2685,7 +2308,7 @@ non avrebbe pi
 considerata libera).  Infine si tenga presente che usare \func{MutexRead} per
 controllare il valore dei mutex prima di proseguire in una operazione di
 sblocco non servirebbe comunque, dato che l'operazione non sarebbe atomica.
-Vedremo in \secref{sec:ipc_lock_file} come sia possibile ottenere
+Vedremo in sez.~\ref{sec:ipc_lock_file} come sia possibile ottenere
 un'interfaccia analoga a quella appena illustrata, senza incorrere in questi
 problemi, usando il file locking\index{file!locking}.
 
@@ -2724,7 +2347,7 @@ ed il suo prototipo 
 
 La funzione, come \func{semget}, è 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
+ripeteremo quanto detto al proposito in sez.~\ref{sec:ipc_sysv_mq}. L'argomento
 \param{size} specifica invece la dimensione, in byte, del segmento, che viene
 comunque arrotondata al multiplo superiore di \const{PAGE\_SIZE}.
 
@@ -2749,18 +2372,7 @@ norma, significa insieme a dei semafori.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct shmid_ds {
-     struct    ipc_perm shm_perm;  /* operation perms */
-     int  shm_segsz;               /* size of segment (bytes) */
-     time_t    shm_atime;          /* last attach time */
-     time_t    shm_dtime;          /* last detach time */
-     time_t    shm_ctime;          /* last change time */
-     unsigned short shm_cpid;      /* pid of creator */
-     unsigned short shm_lpid;      /* pid of last operator */
-     short     shm_nattch;         /* no. of current attaches */
-};
-    \end{lstlisting}
+    \includestruct{listati/shmid_ds.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{shmid\_ds}, associata a ciascun segmento di
@@ -2769,14 +2381,14 @@ struct shmid_ds {
 \end{figure}
 
 A ciascun segmento di memoria condivisa è associata una struttura
-\struct{shmid\_ds}, riportata in \figref{fig:ipc_shmid_ds}.  Come nel caso
+\struct{shmid\_ds}, riportata in fig.~\ref{fig:ipc_shmid_ds}.  Come nel caso
 delle code di messaggi quando si crea un nuovo segmento di memoria condivisa
 con \func{shmget} questa struttura viene inizializzata, in particolare il
 campo \var{shm\_perm} viene inizializzato come illustrato in
-\secref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte
+sez.~\ref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte
 relativamente ai permessi di accesso; per quanto riguarda gli altri campi
 invece:
-\begin{itemize*}
+\begin{itemize}
 \item il campo \var{shm\_segsz}, che esprime la dimensione del segmento, viene
   inizializzato al valore di \param{size}.
 \item il campo \var{shm\_ctime}, che esprime il tempo di creazione del
@@ -2790,7 +2402,7 @@ invece:
   creato il segmento, viene inizializzato al \acr{pid} del processo chiamante.
 \item il campo \var{shm\_nattac}, che esprime il numero di processi agganciati
   al segmento viene inizializzato a zero.
-\end{itemize*}
+\end{itemize}
 
 Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti
 di memoria condivisa esistono una serie di limiti imposti dal sistema.  Alcuni
@@ -2798,7 +2410,7 @@ di questi limiti sono al solito accessibili e modificabili attraverso
 \func{sysctl} o scrivendo direttamente nei rispettivi file di
 \file{/proc/sys/kernel/}. 
 
-In \tabref{tab:ipc_shm_limits} si sono riportate le
+In tab.~\ref{tab:ipc_shm_limits} si sono riportate le
 costanti simboliche associate a ciascuno di essi, il loro significato, i
 valori preimpostati, e, quando presente, il file in \file{/proc/sys/kernel/}
 che permettono di cambiarne il valore. 
@@ -2892,7 +2504,7 @@ corrispondente comportamento della funzione, sono i seguenti:
   \textit{memory locking}\index{memory locking}\footnote{impedisce cioè che la
     memoria usata per il segmento venga salvata su disco dal meccanismo della
     memoria virtuale\index{memoria virtuale}; si ricordi quanto trattato in
-    \secref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo
+    sez.~\ref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo
   l'amministratore può utilizzare questo comando.
 \item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento
   di memoria condivisa. Solo l'amministratore può utilizzare questo comando.
@@ -2936,10 +2548,10 @@ il suo prototipo 
 La funzione inserisce un segmento di memoria condivisa all'interno dello
 spazio di indirizzi del processo, in modo che questo possa accedervi
 direttamente, la situazione dopo l'esecuzione di \func{shmat} è illustrata in
-\figref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
-ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). In
+fig.~\ref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
+ricordi quanto illustrato al proposito in sez.~\ref{sec:proc_mem_layout}). In
 particolare l'indirizzo finale del segmento dati (quello impostato da
-\func{brk}, vedi \secref{sec:proc_mem_sbrk}) non viene influenzato. Si tenga
+\func{brk}, vedi sez.~\ref{sec:proc_mem_sbrk}) non viene influenzato. Si tenga
 presente infine che la funzione ha successo anche se il segmento è stato
 marcato per la cancellazione.
 
@@ -3001,7 +2613,7 @@ In caso di successo la funzione aggiorna anche i seguenti campi di
   aumentato di uno.
 \end{itemize*} 
 
-Come accennato in \secref{sec:proc_fork} un segmento di memoria condivisa
+Come accennato in sez.~\ref{sec:proc_fork} un segmento di memoria condivisa
 agganciato ad un processo viene ereditato da un figlio attraverso una
 \func{fork}, dato che quest'ultimo riceve una copia dello spazio degli
 indirizzi del padre. Invece, dato che attraverso una \func{exec} viene
@@ -3044,6 +2656,55 @@ In caso di successo la funzione aggiorna anche i seguenti campi di
 inoltre la regione di indirizzi usata per il segmento di memoria condivisa
 viene tolta dallo spazio di indirizzi del processo.
 
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/SharedMem.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni che permettono di creare, trovare e
+    rimuovere un segmento di memoria condivisa.}
+  \label{fig:ipc_sysv_shm_func}
+\end{figure}
+
+Come esempio di uso di queste funzioni vediamo come implementare una serie di
+funzioni di libreria che ne semplifichino l'uso, automatizzando le operazioni
+più comuni; il codice, contenuto nel file \file{SharedMem.c}, è riportato in
+fig.~\ref{fig:ipc_sysv_shm_func}.
+
+La prima funzione (\texttt{\small 3--16}) è \func{ShmCreate} che, data una
+chiave, crea il segmento di memoria condivisa restituendo il puntatore allo
+stesso. La funzione comincia (\texttt{\small 6}) con il chiamare
+\func{shmget}, usando il flag \const{IPC\_CREATE} per creare il segmento
+qualora non esista, ed assegnandogli i privilegi specificati dall'argomento
+\var{perm} e la dimensione specificata dall'argomento \var{shm\_size}.  In
+caso di errore (\texttt{\small 7--9}) si ritorna immediatamente un puntatore
+nullo, altrimenti (\texttt{\small 10}) si prosegue agganciando il segmento di
+memoria condivisa al processo con \func{shmat}. In caso di errore
+(\texttt{\small 11--13}) si restituisce di nuovo un puntatore nullo, infine
+(\texttt{\small 14}) si inizializza con \func{memset} il contenuto del
+segmento al valore costante specificato dall'argomento \var{fill}, e poi si
+ritorna il puntatore al segmento stesso.
+
+La seconda funzione (\texttt{\small 17--31}) è \func{ShmFind}, che, data una
+chiave, restituisce l'indirizzo del segmento ad essa associato. Anzitutto
+(\texttt{\small 22}) si richiede l'identificatore del segmento con
+\func{shmget}, ritornando (\texttt{\small 23--25}) un puntatore nullo in caso
+di errore. Poi si prosegue (\texttt{\small 26}) agganciando il segmento al
+processo con \func{shmat}, restituendo (\texttt{\small 27--29}) di nuovo un
+puntatore nullo in caso di errore, se invece non ci sono errori si restituisce
+il puntatore ottenuto da \func{shmat}.
+
+La terza funzione (\texttt{\small 32--51}) è \func{ShmRemove} che, data la
+chiave ed il puntatore associati al segmento di memoria condivisa, prima lo
+sgancia dal processo e poi lo rimuove. Il primo passo (\texttt{\small 37}) è
+la chiamata a \func{shmdt} per sganciare il segmento, restituendo
+(\texttt{\small 38--39}) un valore -1 in caso di errore. Il passo successivo
+(\texttt{\small 41}) è utilizzare \func{shmget} per ottenre l'identificatore
+associato al segmento data la chiave \var{key}. Al solito si restituisce un
+valore di -1 (\texttt{\small 42--45}) in caso di errore, mentre se tutto va
+bene si conclude restituendo un valore nullo.
+
 Benché la memoria condivisa costituisca il meccanismo di intercomunicazione
 fra processi più veloce, essa non è sempre il più appropriato, dato che, come
 abbiamo visto, si avrà comunque la necessità di una sincronizzazione degli
@@ -3051,7 +2712,7 @@ accessi.  Per questo motivo, quando la comunicazione fra processi 
 sequenziale, altri meccanismi come le pipe, le fifo o i socket, che non
 necessitano di sincronizzazione esplicita, sono da preferire. Essa diventa
 l'unico meccanismo possibile quando la comunicazione non è
-sequenziale\footnote{come accennato in \secref{sec:ipc_sysv_mq} per la
+sequenziale\footnote{come accennato in sez.~\ref{sec:ipc_sysv_mq} per la
   comunicazione non sequenziale si possono usare le code di messaggi,
   attraverso l'uso del campo \var{mtype}, ma solo se quest'ultima può essere
   effettuata in forma di messaggio.} o quando non può avvenire secondo una
@@ -3075,7 +2736,7 @@ directory, link simbolici, file normali, ecc.) che saranno salvati in un
 segmento di memoria condivisa cui altri processi potranno accedere per
 ricavare la parte di informazione che interessa.
 
-In \figref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del
+In fig.~\ref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del
 corpo del programma server, insieme alle definizioni delle altre funzioni
 usate nel programma e delle variabili globali, omettendo tutto quello che
 riguarda la gestione delle opzioni e la stampa delle istruzioni di uso a
@@ -3084,63 +2745,8 @@ video; al solito il codice completo si trova con i sorgenti allegati nel file
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/* global variables for shared memory segment */
-struct DirProp {
-    int tot_size;    
-    int tot_files;   
-    int tot_regular; 
-    int tot_fifo;    
-    int tot_link;    
-    int tot_dir;     
-    int tot_block;   
-    int tot_char;    
-    int tot_sock;
-} *shmptr;
-int shmid; 
-int mutex;
-/* main body */
-int main(int argc, char *argv[]) 
-{
-    int i;
-    key_t key;
-    ...
-    if ((argc - optind) != 1) {          /* There must be remaing parameters */
-        printf("Wrong number of arguments %d\n", argc - optind);
-        usage();
-    }
-    if (chdir(argv[1])) {                      /* chdir to be sure dir exist */
-        perror("Cannot find directory to monitor");
-    }
-    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
-    Signal(SIGINT, HandSIGTERM);
-    Signal(SIGQUIT, HandSIGTERM);
-    key = ftok("~/gapil/sources/DirMonitor.c", 1);           /* define a key */
-    shmid = shmget(key, 4096, IPC_CREAT|0666);        /* get a shared memory */
-    if (shmid < 0) {
-        perror("Cannot create shared memory");
-        exit(1);
-    }
-    if ( (shmptr = shmat(shmid, NULL, 0)) == NULL ) {   /* attach to process */
-        perror("Cannot attach segment");
-        exit(1);
-    }
-    if ((mutex = MutexCreate(key)) == -1) {                   /* get a Mutex */
-        perror("Cannot create mutex");
-        exit(1);
-    }
-    /* main loop, monitor directory properties each 10 sec */
-    daemon(1, 0);              /* demonize process, staying in monitored dir */
-    while (1) {
-        MutexLock(mutex);                              /* lock shared memory */
-        memset(shmptr, 0, sizeof(struct DirProp));    /* erase previous data */
-        DirScan(argv[1], ComputeValues);                     /* execute scan */
-        MutexUnlock(mutex);                          /* unlock shared memory */
-        sleep(pause);                              /* sleep until next watch */
-    }
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/DirMonitor.c}
   \end{minipage} 
   \normalsize 
   \caption{Codice della funzione principale del programma \file{DirMonitor.c}.}
@@ -3157,113 +2763,77 @@ Il programma, dopo la sezione, omessa, relativa alla gestione delle opzioni da
 riga di comando (che si limitano alla eventuale stampa di un messaggio di
 aiuto a video ed all'impostazione della durata dell'intervallo con cui viene
 ripetuto il calcolo delle proprietà della directory) controlla (\texttt{\small
-  21--24}) che sia stato specificato il parametro necessario contenente il
+  20--23}) che sia stato specificato il parametro necessario contenente il
 nome della directory da tenere sotto controllo, senza il quale esce
 immediatamente con un messaggio di errore.
 
 Poi, per verificare che il parametro specifichi effettivamente una directory,
-si esegue (\texttt{\small 25--27}) su di esso una \func{chdir}, uscendo
+si esegue (\texttt{\small 24--26}) su di esso una \func{chdir}, uscendo
 immediatamente in caso di errore.  Questa funzione serve anche per impostare
 la directory di lavoro del programma nella directory da tenere sotto
 controllo, in vista del successivo uso della funzione
-\func{daemon}.\footnote{Si noti come si è potuta fare questa scelta,
-  nonostante le indicazioni illustrate in \secref{sec:sess_daemon}, per il
+\func{daemon}.\footnote{si noti come si è potuta fare questa scelta,
+  nonostante le indicazioni illustrate in sez.~\ref{sec:sess_daemon}, per il
   particolare scopo del programma, che necessita comunque di restare
-  all'interno di una directory.} Infine (\texttt{\small 28--30}) si installano
+  all'interno di una directory.} Infine (\texttt{\small 27--29}) si installano
 i gestori per i vari segnali di terminazione che, avendo a che fare con un
 programma che deve essere eseguito come server, sono il solo strumento
 disponibile per concluderne l'esecuzione.
 
-Il passo successivo (\texttt{\small 31--44}) è quello di creare gli oggetti di
-intercomunicazione necessari. Si inizia costruendo (\texttt{\small 31}) la
+Il passo successivo (\texttt{\small 30--39}) è quello di creare gli oggetti di
+intercomunicazione necessari. Si inizia costruendo (\texttt{\small 30}) la
 chiave da usare come riferimento con il nome del programma,\footnote{si è
   usato un riferimento relativo alla home dell'utente, supposto che i sorgenti
   di GaPiL siano stati installati direttamente in essa. Qualora si effettui
   una installazione diversa si dovrà correggere il programma.} dopo di che si
-richiede (\texttt{\small 32}) la creazione di un segmento di memoria condivisa
-con \func{shmget} (una pagina di memoria è sufficiente per i dati che
-useremo), uscendo (\texttt{\small 33--36}) qualora la creazione non abbia
-successo.
-
-Una volta ottenutone l'identificatore in \var{shmid}, si può agganciare
-(\texttt{\small 37--40}) il segmento al processo con \func{shmat} anche in
-questo caso si esce qualora la funzione non abbia successo. Con l'indirizzo
-\var{shmptr} così ottenuto potremo poi accedere alla memoria condivisa, che,
-per come abbiamo lo abbiamo definito, sarà vista nella forma data da
-\struct{DirProp}. Infine (\texttt{\small 41--44}) utilizzando sempre la stessa
-chiave, si crea, tramite le funzioni di interfaccia già descritte in
-\secref{sec:ipc_sysv_sem}, anche un mutex, che utilizzeremo per regolare
-l'accesso alla memoria condivisa.
-
-Una volta completata l'inizializzazione e la creazione degli oggetti di
-intercomunicazione il programma entra nel ciclo principale (\texttt{\small
-  45--54}) dove vengono eseguite indefinitamente le attività di monitoraggio.
-Il primo passo (\texttt{\small 46}) è eseguire \func{daemon} per proseguire con
-l'esecuzione in background come si conviene ad un programma demone; si noti
-che si è mantenuta, usando un valore non nullo del primo argomento, la
-directory di lavoro corrente.
-
-Una volta che il programma è andato in background l'esecuzione prosegue
-(\texttt{\small 47--53}) all'interno di un ciclo infinito: si inizia
-(\texttt{\small 48}) bloccando il mutex con \func{MutexLock} per poter
-accedere alla memoria condivisa (la funzione si bloccherà automaticamente se
-qualche client sta leggendo), poi (\texttt{\small 49}) si cancellano i valori
-precedentemente immagazzinati nella memoria condivisa con \func{memset}, e si
-esegue (\texttt{\small 50}) un nuovo calcolo degli stessi utilizzando la
-funzione \func{DirScan}; infine (\texttt{\small 51}) si sblocca il mutex con
-\func{MutexUnlock}, e si attende (\texttt{\small 52}) per il periodo di tempo
-specificato a riga di comando con l'opzione \code{-p} con una \func{sleep}.
+richiede (\texttt{\small 31}) la creazione di un segmento di memoria condivisa
+con usando la funzione \func{ShmCreate} illustrata in precedenza (una pagina
+di memoria è sufficiente per i dati che useremo), uscendo (\texttt{\small
+  32--35}) qualora la creazione ed il successivo agganciamento al processo non
+abbia successo. Con l'indirizzo \var{shmptr} così ottenuto potremo poi
+accedere alla memoria condivisa, che, per come abbiamo lo abbiamo definito,
+sarà vista nella forma data da \struct{DirProp}. Infine (\texttt{\small
+  36--39}) utilizzando sempre la stessa chiave, si crea, tramite le funzioni
+di interfaccia già descritte in sez.~\ref{sec:ipc_sysv_sem}, anche un mutex,
+che utilizzeremo per regolare l'accesso alla memoria condivisa.
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/* Routine  to compute directory properties inside DirScan */
-int ComputeValues(struct dirent * direntry) 
-{
-    struct stat data;
-    stat(direntry->d_name, &data);                          /* get stat data */
-    shmptr->tot_size += data.st_size;
-    shmptr->tot_files++;
-    if (S_ISREG(data.st_mode)) shmptr->tot_regular++;
-    if (S_ISFIFO(data.st_mode)) shmptr->tot_fifo++;
-    if (S_ISLNK(data.st_mode)) shmptr->tot_link++;
-    if (S_ISDIR(data.st_mode)) shmptr->tot_dir++;
-    if (S_ISBLK(data.st_mode)) shmptr->tot_block++;
-    if (S_ISCHR(data.st_mode)) shmptr->tot_char++;
-    if (S_ISSOCK(data.st_mode)) shmptr->tot_sock++;
-    return 0;
-}
-/* Signal Handler to manage termination */
-void HandSIGTERM(int signo) {
-    MutexLock(mutex);
-    if (shmdt(shmptr)) {
-        perror("Error detaching shared memory");
-        exit(1);
-    }
-    if (shmctl(shmid, IPC_RMID, NULL)) {
-        perror("Cannot remove shared memory segment");
-        exit(1);
-    }
-    MutexRemove(mutex);
-    exit(0);
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ComputeValues.c}
   \end{minipage} 
   \normalsize 
-  \caption{Codice delle funzione ausiliarie usate da \file{DirMonitor.c}.}
+  \caption{Codice delle funzioni ausiliarie usate da \file{DirMonitor.c}.}
   \label{fig:ipc_dirmonitor_sub}
 \end{figure}
 
+Completata l'inizializzazione e la creazione degli oggetti di
+intercomunicazione il programma entra nel ciclo principale (\texttt{\small
+  40--49}) dove vengono eseguite indefinitamente le attività di monitoraggio.
+Il primo passo (\texttt{\small 41}) è eseguire \func{daemon} per proseguire
+con l'esecuzione in background come si conviene ad un programma demone; si
+noti che si è mantenuta, usando un valore non nullo del primo argomento, la
+directory di lavoro corrente.  Una volta che il programma è andato in
+background l'esecuzione prosegue (\texttt{\small 42--48}) all'interno di un
+ciclo infinito: si inizia (\texttt{\small 43}) bloccando il mutex con
+\func{MutexLock} per poter accedere alla memoria condivisa (la funzione si
+bloccherà automaticamente se qualche client sta leggendo), poi (\texttt{\small
+  44}) si cancellano i valori precedentemente immagazzinati nella memoria
+condivisa con \func{memset}, e si esegue (\texttt{\small 45}) un nuovo calcolo
+degli stessi utilizzando la funzione \func{DirScan}; infine (\texttt{\small
+  46}) si sblocca il mutex con \func{MutexUnlock}, e si attende
+(\texttt{\small 47}) per il periodo di tempo specificato a riga di comando con
+l'opzione \code{-p} con una \func{sleep}.
+
 Si noti come per il calcolo dei valori da mantenere nella memoria condivisa si
 sia usata ancora una volta la funzione \func{DirScan}, già utilizzata (e
-descritta in dettaglio) in \secref{sec:file_dir_read}, che ci permette di
+descritta in dettaglio) in sez.~\ref{sec:file_dir_read}, che ci permette di
 effettuare la scansione delle voci della directory, chiamando per ciascuna di
 esse la funzione \func{ComputeValues}, che esegue tutti i calcoli necessari.
 
-Il codice di quest'ultima è riportato in \figref{fig:ipc_dirmonitor_sub}. Come
-si vede la funzione (\texttt{\small 2--16}) è molto semplice e si limita a
-chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da
+Il codice di quest'ultima è riportato in fig.~\ref{fig:ipc_dirmonitor_sub}.
+Come si vede la funzione (\texttt{\small 2--16}) è molto semplice e si limita
+chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da
 ciascuna voce, per ottenerne i dati, che poi utilizza per incrementare i vari
 contatori nella memoria condivisa, cui accede grazie alla variabile globale
 \var{shmptr}.
@@ -3274,58 +2844,23 @@ effettuare nessun controllo e si pu
 condivisa usando \var{shmptr} per riempire i campi della struttura
 \struct{DirProp}; così prima (\texttt{\small 6--7}) si sommano le dimensioni
 dei file ed il loro numero, poi, utilizzando le macro di
-\tabref{tab:file_type_macro}, si contano (\texttt{\small 8--14}) quanti ce ne
-sono per ciascun tipo.
-
-In \figref{fig:ipc_dirmonitor_sub} è riportato anche (\texttt{\small 17--30})
-il codice del gestore dei segnali di terminazione, usato per chiudere il
-programma. Esso, oltre a provocare l'uscita del programma, si incarica anche
-di cancellare tutti gli oggetti di intercomunicazione non più necessari.  Per
-questo anzitutto (\texttt{\small 19}) acquisisce il mutex con
+tab.~\ref{tab:file_type_macro}, si contano (\texttt{\small 8--14}) quanti ce
+ne sono per ciascun tipo.
+
+In fig.~\ref{fig:ipc_dirmonitor_sub} è riportato anche il codice
+(\texttt{\small 17--23}) del gestore dei segnali di terminazione, usato per
+chiudere il programma. Esso, oltre a provocare l'uscita del programma, si
+incarica anche di cancellare tutti gli oggetti di intercomunicazione non più
+necessari.  Per questo anzitutto (\texttt{\small 19}) acquisisce il mutex con
 \func{MutexLock}, per evitare di operare mentre un client sta ancora leggendo
-i dati, dopo di che (\texttt{\small 20--23}) prima distacca il segmento di
-memoria condivisa con \func{shmad} e poi (\texttt{\small 24--27}) lo cancella
-con \func{shctl}.  Infine (\texttt{\small 28}) rimuove il mutex con
-\func{MutexRemove} ed esce.
+i dati, dopo di che (\texttt{\small 20}) distacca e rimuove il segmento di
+memoria condivisa usando \func{ShmRemove}.  Infine (\texttt{\small 21})
+rimuove il mutex con \func{MutexRemove} ed esce (\texttt{\small 22}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-int main(int argc, char *argv[]) 
-{
-    int i;
-    key_t key;
-    ...
-    /* create needed IPC objects */
-    key = ftok("~/gapil/sources/DirMonitor.c", 1);           /* define a key */
-    shmid = shmget(key, 4096, 0);                /* get the shared memory ID */
-    if (shmid < 0) {
-        perror("Cannot find shared memory");
-        exit(1);
-    }
-    if ( (shmptr = shmat(shmid, NULL, 0)) == NULL ) {   /* attach to process */
-        perror("Cannot attach segment");
-        exit(1);
-    }
-    if ((mutex = MutexFind(key)) == -1) {                   /* get the Mutex */
-        perror("Cannot find mutex");
-        exit(1);
-    }
-    /* main loop */
-    MutexLock(mutex);                                  /* lock shared memory */
-    printf("Ci sono %d file dati\n", shmptr->tot_regular);
-    printf("Ci sono %d directory\n", shmptr->tot_dir);
-    printf("Ci sono %d link\n", shmptr->tot_link);
-    printf("Ci sono %d fifo\n", shmptr->tot_fifo);
-    printf("Ci sono %d socket\n", shmptr->tot_sock);
-    printf("Ci sono %d device a caratteri\n", shmptr->tot_char);
-    printf("Ci sono %d device a blocchi\n", shmptr->tot_block);
-    printf("Totale  %d file, per %d byte\n",
-           shmptr->tot_files, shmptr->tot_size);
-    MutexUnlock(mutex);                              /* unlock shared memory */
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6 cm}
+    \includecodesample{listati/ReadMonitor.c}
   \end{minipage} 
   \normalsize 
   \caption{Codice del programma client del monitor delle proprietà di una
@@ -3333,31 +2868,25 @@ int main(int argc, char *argv[])
   \label{fig:ipc_dirmonitor_client}
 \end{figure}
 
-Il codice del client, che permette di leggere le informazioni mantenute nella
-memoria condivisa, è riportato in \figref{fig:ipc_dirmonitor_client}. Al
-solito si è omessa la sezione di gestione delle opzioni e la funzione che
-stampa a video le istruzioni; il codice completo è nei sorgenti allegati, nel
-file \file{ReadMonitor.c}.
+Il codice del client usato per leggere le informazioni mantenute nella memoria
+condivisa è riportato in fig.~\ref{fig:ipc_dirmonitor_client}. Al solito si è
+omessa la sezione di gestione delle opzioni e la funzione che stampa a video
+le istruzioni; il codice completo è nei sorgenti allegati, nel file
+\file{ReadMonitor.c}.
 
-Una volta completata la gestione delle opzioni a riga di comando il programma
+Una volta conclusa la gestione delle opzioni a riga di comando il programma
 rigenera (\texttt{\small 7}) con \func{ftok} la stessa chiave usata dal server
 per identificare il segmento di memoria condivisa ed il mutex, poi
-(\texttt{\small 8}) si richiede con \func{semget} l'identificatore della
-memoria condivisa, ma in questo caso si vuole che esso esista di già; al
-solito (\texttt{\small 9--12}) si esce in caso di errore. Una volta ottenuto
-l'identificatore in \var{shmid} si può (\texttt{\small 13--16}) agganciare il
-segmento al processo all'indirizzo \func{shmptr}; anche in questo caso si
-chiude immediatamente il programma se qualcosa non funziona.  Infine
+(\texttt{\small 8}) richiede con \func{ShmFind} l'indirizzo della memoria
+condivisa agganciando al contempo il segmento al processo, Infine
 (\texttt{\small 17--20}) con \func{MutexFind} si richiede l'identificatore del
-mutex.
-
-Una volta completata l'inizializzazione ed ottenuti i riferimenti agli oggetti
+mutex.  Completata l'inizializzazione ed ottenuti i riferimenti agli oggetti
 di intercomunicazione necessari viene eseguito il corpo principale del
 programma (\texttt{\small 21--33}); si comincia (\texttt{\small 22})
 acquisendo il mutex con \func{MutexLock}; qui avviene il blocco del processo
 se la memoria condivisa non è disponibile.  Poi (\texttt{\small 23--31}) si
 stampano i vari valori mantenuti nella memoria condivisa attraverso l'uso di
-\var{shmptr}. Infine (\texttt{\small 41}) con \func{MutexUnlock} si rilascia
+\var{shmptr}.  Infine (\texttt{\small 41}) con \func{MutexUnlock} si rilascia
 il mutex, prima di uscire.
 
 Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando
@@ -3399,8 +2928,8 @@ key        msqid      owner      perms      used-bytes   messages
 \end{verbatim}%$
 
 Se a questo punto aggiungiamo un file, ad esempio con \code{touch prova},
-potremo verificare (passati nel peggiore dei casi almeno 10 secondi, cioè
-l'intervallo scelto per la rilettura dei dati), che:
+potremo verificare che, passati nel peggiore dei casi almeno 10 secondi (o
+l'eventuale altro intervallo impostato per la rilettura dei dati) avremo:
 \begin{verbatim}
 [piccardi@gont sources]$ ./readmon 
 Ci sono 69 file dati
@@ -3413,14 +2942,15 @@ Ci sono 0 device a blocchi
 Totale  72 file, per 489887 byte
 \end{verbatim}%$
 
-Infine potremo terminare il server con il comando \code{killall dirmonitor},
-nel qual caso, ripetendo la lettura otterremo che:
+A questo punto possiamo far uscire il server inviandogli un segnale di
+\const{SIGTERM} con il comando \code{killall dirmonitor}, a questo punto
+ripetendo la lettura, otterremo un errore:
 \begin{verbatim}
 [piccardi@gont sources]$ ./readmon 
 Cannot find shared memory: No such file or directory
 \end{verbatim}%$
-e potremo verificare che anche gli oggetti di intercomunicazione sono stati
-cancellati:
+e inoltre potremo anche verificare che anche gli oggetti di intercomunicazione
+visti in precedenza sono stati regolarmente  cancellati:
 \begin{verbatim}
 [piccardi@gont sources]$ ipcs
 ------ Shared Memory Segments --------
@@ -3438,7 +2968,7 @@ key        msqid      owner      perms      used-bytes   messages
 %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
 %% riferimento alle strutture con cui il kernel implementa i segmenti di memoria
 %% condivisa; uno schema semplificato della struttura è illustrato in
-%% \figref{fig:ipc_shm_struct}. 
+%% fig.~\ref{fig:ipc_shm_struct}. 
 
 %% \begin{figure}[htb]
 %%   \centering
@@ -3454,7 +2984,7 @@ key        msqid      owner      perms      used-bytes   messages
 \section{Tecniche alternative}
 \label{sec:ipc_alternatives}
 
-Come abbiamo detto in \secref{sec:ipc_sysv_generic}, e ripreso nella
+Come abbiamo detto in sez.~\ref{sec:ipc_sysv_generic}, e ripreso nella
 descrizione dei singoli oggetti che ne fan parte, il \textit{SysV IPC}
 presenta numerosi problemi; in \cite{APUE}\footnote{in particolare nel
   capitolo 14.}  Stevens ne effettua una accurata analisi (alcuni dei concetti
@@ -3468,7 +2998,7 @@ alternative, che vogliamo riprendere in questa sezione.
 Le code di messaggi sono probabilmente il meno usato degli oggetti del
 \textit{SysV IPC}; esse infatti nacquero principalmente come meccanismo di
 comunicazione bidirezionale quando ancora le pipe erano unidirezionali; con la
-disponibilità di \func{socketpair} (vedi \secref{sec:ipc_socketpair}) o
+disponibilità di \func{socketpair} (vedi sez.~\ref{sec:ipc_socketpair}) o
 utilizzando una coppia di pipe, si può ottenere questo risultato senza
 incorrere nelle complicazioni introdotte dal \textit{SysV IPC}.
 
@@ -3485,7 +3015,7 @@ relativamente poco diffuso.
 \label{sec:ipc_file_lock}
 
 \index{file!di lock|(}
-Come illustrato in \secref{sec:ipc_sysv_sem} i semafori del \textit{SysV IPC}
+Come illustrato in sez.~\ref{sec:ipc_sysv_sem} i semafori del \textit{SysV IPC}
 presentano una interfaccia inutilmente complessa e con alcuni difetti
 strutturali, per questo quando si ha una semplice esigenza di sincronizzazione
 per la quale basterebbe un semaforo binario (quello che abbiamo definito come
@@ -3497,7 +3027,7 @@ La prima possibilit
 dei \textsl{file di lock} (per i quali esiste anche una opportuna directory,
 \file{/var/lock}, nel filesystem standard). Per questo si usa la
 caratteristica della funzione \func{open} (illustrata in
-\secref{sec:file_open}) che prevede\footnote{questo è quanto dettato dallo
+sez.~\ref{sec:file_open}) che prevede\footnote{questo è quanto dettato dallo
   standard POSIX.1, ciò non toglie che in alcune implementazioni questa
   tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si
   è comunque soggetti alla possibilità di una race   
@@ -3509,7 +3039,7 @@ risorsa ad esso associata) mentre il rilascio si pu
 ad \func{unlink}.
 
 Un esempio dell'uso di questa funzione è mostrato dalle funzioni
-\func{LockFile} ed \func{UnlockFile} riportate in \figref{fig:ipc_file_lock}
+\func{LockFile} ed \func{UnlockFile} riportate in fig.~\ref{fig:ipc_file_lock}
 (sono contenute in \file{LockFile.c}, un'altro dei sorgenti allegati alla
 guida) che permettono rispettivamente di creare e rimuovere un \textsl{file di
   lock}. Come si può notare entrambe le funzioni sono elementari; la prima
@@ -3519,26 +3049,8 @@ cancella con \func{unlink}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>                               /* unix standard functions */
-/*
- * Function LockFile:
- */
-int LockFile(const char* path_name)
-{
-    return open(path_name, O_EXCL|O_CREAT);
-}
-/*
- * Function UnlockFile:
- */
-int UnlockFile(const char* path_name) 
-{
-    return unlink(path_name);
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/LockFile.c}
   \end{minipage} 
   \normalsize 
   \caption{Il codice delle funzioni \func{LockFile} e \func{UnlockFile} che
@@ -3547,16 +3059,17 @@ int UnlockFile(const char* path_name)
 \end{figure}
 
 Uno dei limiti di questa tecnica è che, come abbiamo già accennato in
-\secref{sec:file_open}, questo comportamento di \func{open} può non funzionare
-(la funzione viene eseguita, ma non è garantita l'atomicità dell'operazione)
-se il filesystem su cui si va ad operare è su NFS; in tal caso si può adottare
-una tecnica alternativa che prevede l'uso della \func{link} per creare come
-\textsl{file di lock} un hard link ad un file esistente; se il link esiste già
-e la funzione fallisce, significa che la risorsa è bloccata e potrà essere
-sbloccata solo con un \func{unlink}, altrimenti il link è creato ed il lock
-acquisito; il controllo e l'eventuale acquisizione sono atomici; la soluzione
-funziona anche su NFS, ma ha un'altro difetto è che è quello di poterla usare
-solo se si opera all'interno di uno stesso filesystem.
+sez.~\ref{sec:file_open}, questo comportamento di \func{open} può non
+funzionare (la funzione viene eseguita, ma non è garantita l'atomicità
+dell'operazione) se il filesystem su cui si va ad operare è su NFS; in tal
+caso si può adottare una tecnica alternativa che prevede l'uso della
+\func{link} per creare come \textsl{file di lock} un hard link ad un file
+esistente; se il link esiste già e la funzione fallisce, significa che la
+risorsa è bloccata e potrà essere sbloccata solo con un \func{unlink},
+altrimenti il link è creato ed il lock acquisito; il controllo e l'eventuale
+acquisizione sono atomici; la soluzione funziona anche su NFS, ma ha un'altro
+difetto è che è quello di poterla usare solo se si opera all'interno di uno
+stesso filesystem.
 
 Un generale comunque l'uso di un \textsl{file di lock} presenta parecchi
 problemi, che non lo rendono una alternativa praticabile per la
@@ -3581,7 +3094,7 @@ disponibile.\index{file!di lock|)}
 Dato che i file di lock\index{file!di lock} presentano gli inconvenienti
 illustrati in precedenza, la tecnica alternativa di sincronizzazione più
 comune è quella di fare ricorso al \textit{file locking}\index{file!locking}
-(trattato in \secref{sec:file_locking}) usando \func{fcntl} su un file creato
+(trattato in sez.~\ref{sec:file_locking}) usando \func{fcntl} su un file creato
 per l'occasione per ottenere un write lock. In questo modo potremo usare il
 lock come un \textit{mutex}: per bloccare la risorsa basterà acquisire il
 lock, per sbloccarla basterà rilasciare il lock. Una richiesta fatta con un
@@ -3599,64 +3112,8 @@ leggermente pi
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/* Function CreateMutex: Create a mutex using file locking. */
-int CreateMutex(const char *path_name)
-{
-    return open(path_name, O_EXCL|O_CREAT);
-}
-/* Function UnlockMutex: unlock a file. */
-int FindMutex(const char *path_name)
-{
-    return open(path_name, O_RDWR);
-}
-/* Function LockMutex: lock mutex using file locking. */
-int LockMutex(int fd)
-{
-    struct flock lock;                                /* file lock structure */
-    /* set flock structure */
-    lock.l_type = F_WRLCK;                        /* set type: read or write */
-    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
-    lock.l_start = 0;                  /* set the start of the locked region */
-    lock.l_len = 0;                   /* set the length of the locked region */
-    /* do locking */
-    return fcntl(fd, F_SETLKW, &lock);
-}
-/* Function UnlockMutex: unlock a file. */
-int UnlockMutex(int fd)
-{
-    struct flock lock;                                /* file lock structure */
-    /* set flock structure */
-    lock.l_type = F_UNLCK;                               /* set type: unlock */
-    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
-    lock.l_start = 0;                  /* set the start of the locked region */
-    lock.l_len = 0;                   /* set the length of the locked region */
-    /* do locking */
-    return fcntl(fd, F_SETLK, &lock);
-}
-/* Function RemoveMutex: remove a mutex (unlinking the lock file). */
-int RemoveMutex(const char *path_name)
-{
-    return unlink(path_name);
-}
-/* Function ReadMutex: read a mutex status. */
-int ReadMutex(int fd)
-{
-    int res;
-    struct flock lock;                                /* file lock structure */
-    /* set flock structure */
-    lock.l_type = F_WRLCK;                               /* set type: unlock */
-    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
-    lock.l_start = 0;                  /* set the start of the locked region */
-    lock.l_len = 0;                   /* set the length of the locked region */
-    /* do locking */
-    if ( (res = fcntl(fd, F_GETLK, &lock)) ) {
-        return res;
-    }
-    return lock.l_type;
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MutexLocking.c}
   \end{minipage} 
   \normalsize 
   \caption{Il codice delle funzioni che permettono per la gestione dei 
@@ -3665,7 +3122,7 @@ int ReadMutex(int fd)
 \end{figure}
 
 Il codice delle varie funzioni usate per implementare un mutex utilizzando il
-file locking\index{file!locking} è riportato in \figref{fig:ipc_flock_mutex};
+file locking\index{file!locking} è riportato in fig.~\ref{fig:ipc_flock_mutex};
 si è mantenuta volutamente una struttura analoga alle precedenti funzioni che
 usano i semafori, anche se le due interfacce non possono essere completamente
 equivalenti, specie per quanto riguarda la rimozione del mutex.
@@ -3699,7 +3156,7 @@ rilasciare il mutex. La funzione 
 caso si inizializza (\texttt{\small 28--31}) la struttura \var{lock} per il
 rilascio del lock, che viene effettuato (\texttt{\small 33}) con la opportuna
 chiamata a \func{fcntl}. Avendo usato il file locking in semantica POSIX (si
-riveda quanto detto \secref{sec:file_posix_lock}) solo il processo che ha
+riveda quanto detto sez.~\ref{sec:file_posix_lock}) solo il processo che ha
 precedentemente eseguito il lock può sbloccare il mutex.
 
 La quinta funzione (\texttt{\small 36--39}) è \func{RemoveMutex} e serve a
@@ -3729,8 +3186,8 @@ successo, ad indicare che il mutex 
 
 Basandosi sulla semantica dei file lock POSIX valgono tutte le considerazioni
 relative al comportamento di questi ultimi fatte in
-\secref{sec:file_posix_lock}; questo significa ad esempio che, al contrario di
-quanto avveniva con l'interfaccia basata sui semafori, chiamate multiple a
+sez.~\ref{sec:file_posix_lock}; questo significa ad esempio che, al contrario
+di quanto avveniva con l'interfaccia basata sui semafori, chiamate multiple a
 \func{UnlockMutex} o \func{LockMutex} non si cumulano e non danno perciò
 nessun inconveniente.
 
@@ -3744,7 +3201,7 @@ una valida alternativa alle code di messaggi; nella stessa situazione si pu
 evitare l'uso di una memoria condivisa facendo ricorso al cosiddetto
 \textit{memory mapping} anonimo.
 
-In \secref{sec:file_memory_map} abbiamo visto come sia possibile mappare il
+In sez.~\ref{sec:file_memory_map} abbiamo visto come sia possibile mappare il
 contenuto di un file nella memoria di un processo, e che, quando viene usato
 il flag \const{MAP\_SHARED}, le modifiche effettuate al contenuto del file
 vengono viste da tutti i processi che lo hanno mappato. Utilizzare questa
@@ -3765,15 +3222,15 @@ il \textit{memory mapping} anonimo.\footnote{nei sistemi derivati da SysV una
   restano in memoria e possono essere riletti secondo le stesse modalità usate
   nel \textit{memory mapping} anonimo.} Vedremo come utilizzare questa tecnica
 più avanti, quando realizzeremo una nuova versione del monitor visto in
-\secref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete.
+sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete.
 
 
 
-\section{La comunicazione fra processi di POSIX}
+\section{Il sistema di comunicazione fra processi di POSIX}
 \label{sec:ipc_posix}
 
 Per superare i numerosi problemi del \textit{SysV IPC}, evidenziati per i suoi
-aspetti generali in coda a \secref{sec:ipc_sysv_generic} e per i singoli
+aspetti generali in coda a sez.~\ref{sec:ipc_sysv_generic} e per i singoli
 oggetti nei paragrafi successivi, lo standard POSIX.1b ha introdotto dei nuovi
 meccanismi di comunicazione, che vanno sotto il nome di POSIX IPC, definendo
 una interfaccia completamente nuova, che tratteremo in questa sezione.
@@ -3812,28 +3269,30 @@ Data la assoluta genericit
 è pertanto subordinato in maniera quasi completa alla relativa
 implementazione.\footnote{tanto che Stevens in \cite{UNP2} cita questo caso
   come un esempio della maniera standard usata dallo standard POSIX per
-  consentire implementazioni non standardizzabili.} Nel caso di Linux per
-quanto riguarda la memoria condivisa, tutto viene creato nella directory
-\file{/dev/shm}, ed i nomi sono presi come pathname assoluto (comprendente
-eventuali sottodirectory) rispetto a questa radice (per maggiori dettagli si
-veda quanto illustrato in \secref{sec:ipc_posix_shm}). Lo stesso accade per
-l'implementazione sperimentale delle code di messaggi, che però fa riferimento
-alla directory \file{/dev/mqueue}.
+  consentire implementazioni non standardizzabili.} Nel caso di Linux, sia per
+quanto riguarda la memoria condivisa, che per quanto riguarda le code di
+messaggi, tutto viene creato usando come radici delle opportune directory
+(rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per i dettagli si
+faccia riferimento a sez.~\ref{sec:ipc_posix_shm} e
+sez.~\ref{sec:ipc_posix_mq}) ed i nomi specificati nelle relative funzioni
+sono considerati come un pathname assoluto (comprendente eventuali
+sottodirectory) rispetto a queste radici.
 
 Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti
 nell'albero dei file, e possono essere maneggiati con le usuali funzioni e
-comandi di accesso ai file,\footnote{questo è vero nel caso di Linux, che usa
-  una implementazione che lo consente, non è detto che altrettanto valga per
-  altri kernel. In particolare per la memoria condivisa, come si può
-  facilmente evincere con uno \cmd{strace}, le system call utilizzate sono le
-  stesse, in quanto essa è realizzata con file in uno speciale filesystem.}
-che funzionano come su dei file normali.
+comandi di accesso ai file,\footnote{questo è ancora più vero nel caso di
+  Linux, che usa una implementazione che lo consente, non è detto che
+  altrettanto valga per altri kernel. In particolare sia la memoria condivisa
+  che per le code di messaggi, come si può facilmente evincere con uno
+  \cmd{strace}, le system call utilizzate sono le stesse, in quanto esse sono
+  realizzate con dei file in speciali filesystem.}  che funzionano come su dei
+file normali.
 
 In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai
 permessi dei file, e il controllo di accesso segue esattamente la stessa
-semantica (quella illustrata in \secref{sec:file_access_control}), invece di
+semantica (quella illustrata in sez.~\ref{sec:file_access_control}), invece di
 quella particolare (si ricordi quanto visto in
-\secref{sec:ipc_sysv_access_control}) usata per gli oggetti del SysV IPC. Per
+sez.~\ref{sec:ipc_sysv_access_control}) usata per gli oggetti del SysV IPC. Per
 quanto riguarda l'attribuzione dell'utente e del gruppo proprietari
 dell'oggetto alla creazione di quest'ultimo essa viene effettuata secondo la
 semantica SysV (essi corrispondono cioè a userid e groupid effettivi del
@@ -3847,22 +3306,26 @@ processo che esegue la creazione).
 Le code di messaggi non sono ancora supportate nel kernel ufficiale, esiste
 però una implementazione sperimentale di Michal Wronski e Krzysztof
 Benedyczak,\footnote{i patch al kernel e la relativa libreria possono essere
-  trovati \href{http://www.mat.uni.torun.pl/~wrona/posix_ipc}
-  {http://www.mat.uni.torun.pl/\~{}wrona/posix\_ipc}.}.  In generale, come le
-corrispettive del SysV IPC, le code di messaggi sono poco usate, dato che i
-socket\index{socket}, nei casi in cui sono sufficienti, sono più comodi, e che
-in casi più complessi la comunicazione può essere gestita direttamente con
-mutex e memoria condivisa con tutta la flessibilità che occorre.
+  trovati su \href{http://www.mat.uni.torun.pl/~wrona/posix_ipc}
+  {http://www.mat.uni.torun.pl/\tild{}wrona/posix\_ipc}, questi sono stati
+  inseriti nel kernel ufficiale a partire dalla versione 2.6.6-rc1.}.  In
+generale, come le corrispettive del SysV IPC, le code di messaggi sono poco
+usate, dato che i socket\index{socket}, nei casi in cui sono sufficienti, sono
+più comodi, e che in casi più complessi la comunicazione può essere gestita
+direttamente con mutex e memoria condivisa con tutta la flessibilità che
+occorre.
 
 Per poter utilizzare le code di messaggi, oltre ad utilizzare un kernel cui
 siano stati opportunamente applicati i relativi patch, occorre utilizzare la
 libreria \file{mqueue}\footnote{i programmi che usano le code di messaggi cioè
   devono essere compilati aggiungendo l'opzione \code{-lmqueue} al comando
-  \cmd{gcc}, dato che le funzioni non fanno parte della libreria standard.}
-che contiene le funzioni dell'interfaccia POSIX.\footnote{in realtà
-  l'implementazione è realizzata tramite delle speciali chiamate ad
-  \func{ioctl} sui file del filesystem speciale su cui vengono mantenuti
-  questi oggetti di IPC.}
+  \cmd{gcc}, dato che le funzioni non fanno parte della libreria standard, in
+  corrispondenza all'inclusione del supporto nel kernel ufficiale, anche le
+  relative funzioni sono state inserite nelle \acr{glibc} a partire dalla
+  versione 2.3.4.}  che contiene le funzioni dell'interfaccia
+POSIX.\footnote{in realtà l'implementazione è realizzata tramite delle
+  speciali chiamate ad \func{ioctl} sui file del filesystem speciale su cui
+  vengono mantenuti questi oggetti di IPC.}
 
 
 La libreria inoltre richiede la presenza dell'apposito filesystem di tipo
@@ -3919,7 +3382,7 @@ stesso oggetto, consentendo cos
 La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
 possono essere specificati per \param{oflag}, che deve essere specificato come
 maschera binaria; i valori possibili per i vari bit sono quelli visti in
-\tabref{tab:file_open_flags} dei quali però \func{mq\_open} riconosce solo i
+tab.~\ref{tab:file_open_flags} dei quali però \func{mq\_open} riconosce solo i
 seguenti:
 \begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
 \item[\const{O\_RDONLY}] Apre la coda solo per la ricezione di messaggi. Il
@@ -3955,19 +3418,12 @@ solo i permessi di lettura e scrittura. Oltre ai permessi di creazione possono
 essere specificati anche gli attributi specifici della coda tramite
 l'argomento \param{attr}; quest'ultimo è un puntatore ad una apposita
 struttura \struct{mq\_attr}, la cui definizione è riportata in
-\figref{fig:ipc_mq_attr}.
+fig.~\ref{fig:ipc_mq_attr}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}
-struct mq_attr {
-        long    mq_flags;       /* message queue flags                  */
-        long    mq_maxmsg;      /* maximum number of messages           */
-        long    mq_msgsize;     /* maximum message size                 */
-        long    mq_curmsgs;     /* number of messages currently queued  */
-};
-    \end{lstlisting}
+    \includestruct{listati/mq_attr.h}
   \end{minipage} 
   \normalsize
   \caption{La struttura \structd{mq\_attr}, contenente gli attributi di una
@@ -4010,7 +3466,7 @@ essere richiesta da qualche altro processo.
 Quando si vuole effettivamente rimuovere una coda dal sistema occorre usare la
 funzione \funcd{mq\_unlink}, il cui prototipo è:
 \begin{prototype}{mqueue.h}
-{int mq_unlink(const char *name)}
+{int mq\_unlink(const char *name)}
 
 Rimuove una coda di messaggi.
   
@@ -4132,11 +3588,12 @@ prototipi sono:
 \begin{functions}
   \headdecl{mqueue.h} 
   
-  \funcdecl{ssize\_t mq\_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
-    unsigned int *msg_prio)} Effettua la ricezione di un messaggio da una coda.
+  \funcdecl{ssize\_t mq\_receive(mqd\_t mqdes, char *msg\_ptr, size\_t
+    msg\_len, unsigned int *msg\_prio)}   
+  Effettua la ricezione di un messaggio da una coda.
   
   \funcdecl{ssize\_t mq\_timedreceive(mqd\_t mqdes, char *msg\_ptr, size\_t
-    msg\_len, unsigned int *msg\_prio, const struct timespec *abs'_timeout)}
+    msg\_len, unsigned int *msg\_prio, const struct timespec *abs\_timeout)}
   Effettua la ricezione di un messaggio da una coda entro il tempo
   \param{abs\_timeout}.
   
@@ -4153,25 +3610,34 @@ prototipi sono:
     \item[\errcode{ETIMEDOUT}] La ricezione del messaggio non è stata
       effettuata entro il tempo stabilito.
     \end{errlist}    
-    \errval{EBADF}, \errval{EINTR}, \errval{ENOMEM}, o \errval{EINVAL}.}
+    ed inoltre \errval{EBADF}, \errval{EINTR}, \errval{ENOMEM}, o
+    \errval{EINVAL}.}
 \end{functions}
 
 La funzione estrae dalla coda il messaggio a priorità più alta, o il più
-vecchio fra quelli della stessa priorità, una volta ricevuto il messaggio
+vecchio fra quelli della stessa priorità. Una volta ricevuto il messaggio
 viene tolto dalla coda e la sua dimensione viene restituita come valore di
-ritorno. Se la dimensione specificata da \param{msg\_len} non è sufficiente a
-contenere il messaggio le funzioni, al contrario di quanto avveniva nelle code
-di messaggi di SysV, ritornano un errore di \errcode{EMSGSIZE} senza estrarre
-il messaggio.  È pertanto opportuno chiamare sempre \func{mq\_getaddr} prima
-di eseguire una ricezione, per allocare per i messaggi dei buffer di
-dimensione opportuna.
+ritorno.
 
-Se si specifica un valore non nullo per l'argomento \param{msg\_prio} il
-valore della priorità del messaggio viene memorizzato all'indirizzo da esso
-puntato. Si noti che con le code di messaggi POSIX non si ha la possibilità di
-selezionare quale messaggio estrarre in base alla priorità, a differenza di
-quanto avveniva con le code di messaggi di SysV che permettono la selezione in
-base al valore del campo \var{mtype}.
+Se la dimensione specificata da \param{msg\_len} non è sufficiente a contenere
+il messaggio, entrambe le funzioni, al contrario di quanto avveniva nelle code
+di messaggi di SysV, ritornano un errore di \errcode{EMSGSIZE} senza estrarre
+il messaggio.  È pertanto opportuno eseguire sempre una chiamata a
+\func{mq\_getaddr} prima di eseguire una ricezione, in modo da ottenere la
+dimensione massima dei messaggi sulla coda, per poter essere in grado di
+allocare dei buffer sufficientemente ampi per la lettura.
+
+Se si specifica un puntatore per l'argomento \param{msg\_prio} il valore della
+priorità del messaggio viene memorizzato all'indirizzo da esso indicato.
+Qualora non interessi usare la priorità dei messaggi si può specificare
+\var{NULL}, ed usare un valore nullo della priorità nelle chiamate a
+\func{mq\_send}.
+
+Si noti che con le code di messaggi POSIX non si ha la possibilità di
+selezionare quale messaggio estrarre con delle condizioni sulla priorità, a
+differenza di quanto avveniva con le code di messaggi di SysV che permettono
+invece la selezione in base al valore del campo \var{mtype}. Qualora non
+interessi usare la priorità dei messaggi si
 
 Qualora la coda sia vuota entrambe le funzioni si bloccano, a meno che non si
 sia selezionata la modalità non bloccante; in tal caso entrambe ritornano
@@ -4180,6 +3646,99 @@ differenza fra le due funzioni 
 passato il tempo massimo \param{abs\_timeout} ritorna comunque con un errore
 di \errcode{ETIMEDOUT}.
 
+Uno dei problemi sottolineati da Stevens in \cite{UNP2}, comuni ad entrambe le
+tipologie di code messaggi, è che non è possibile per chi riceve identificare
+chi è che ha inviato il messaggio, in particolare non è possibile sapere da
+quale utente esso provenga. Infatti, in mancanza di un meccanismo interno al
+kernel, anche se si possono inserire delle informazioni nel messaggio, queste
+non possono essere credute, essendo completamente dipendenti da chi lo invia.
+Vedremo però come, attraverso l'uso del meccanismo di notifica, sia possibile
+superare in parte questo problema.
+
+Una caratteristica specifica delle code di messaggi POSIX è la possibilità di
+usufruire di un meccanismo di notifica asincrono; questo può essere attivato
+usando la funzione \funcd{mq\_notify}, il cui prototipo è:
+\begin{prototype}{mqueue.h}
+{int mq\_notify(mqd\_t mqdes, const struct sigevent *notification)}
+
+Attiva il meccanismo di notifica per la coda \param{mqdes}.
+  
+\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+  errore; nel quel caso \var{errno} assumerà i valori: 
+    \begin{errlist}
+    \item[\errcode{EBUSY}] C'è già un processo registrato per la notifica.
+    \item[\errcode{EBADF}] Il descrittore non fa riferimento ad una coda di
+      messaggi.
+    \end{errlist}}
+\end{prototype}
+
+Il meccanismo di notifica permette di segnalare in maniera asincrona ad un
+processo la presenza di dati sulla coda, in modo da evitare la necessità di
+bloccarsi nell'attesa. Per far questo un processo deve registrarsi con la
+funzione \func{mq\_notify}, ed il meccanismo è disponibile per un solo
+processo alla volta per ciascuna coda.
+
+Il comportamento di \func{mq\_notify} dipende dal valore dell'argomento
+\param{notification}, che è un puntatore ad una apposita struttura
+\struct{sigevent}, (definita in fig.~\ref{fig:file_sigevent}) introdotta dallo
+standard POSIX.1b per gestire la notifica di eventi; per altri dettagli si può
+vedere quanto detto in sez.~\ref{sec:file_asyncronous_io} a proposito dell'uso
+della stessa struttura per l'invio dei segnali usati per l'I/O asincrono.
+
+Attraverso questa struttura si possono impostare le modalità con cui viene
+effettuata la notifica; in particolare il campo \var{sigev\_notify} deve
+essere posto a \const{SIGEV\_SIGNAL}\footnote{il meccanismo di notifica basato
+  sui thread, specificato tramite il valore \const{SIGEV\_THREAD}, non è
+  implementato.} ed il campo \var{sigev\_signo} deve indicare il valore del
+segnale che sarà inviato al processo. Inoltre il campo \var{sigev\_value} è il
+puntatore ad una struttura \struct{sigval\_t} (definita in
+fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore del segnale un
+valore numerico o un indirizzo,\footnote{per il suo uso si riveda la
+  trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei segnali
+  real-time.} posto che questo sia installato nella forma estesa vista in
+sez.~\ref{sec:sig_sigaction}.
+
+La funzione registra il processo chiamante per la notifica se
+\param{notification} punta ad una struttura \struct{sigevent} opportunamente
+inizializzata, o cancella una precedente registrazione se è \val{NULL}. Dato
+che un solo processo alla volta può essere registrato, la funzione fallisce
+con \errcode{EBUSY} se c'è un altro processo già registrato.  Si tenga
+presente inoltre che alla chiusura del descrittore associato alla coda (e
+quindi anche all'uscita del processo) ogni eventuale registrazione di notifica
+presente viene cancellata.
+
+La notifica del segnale avviene all'arrivo di un messaggio in una coda vuota
+(cioè solo se sulla coda non ci sono messaggi) e se non c'è nessun processo
+bloccato in una chiamata a \func{mq\_receive}, in questo caso infatti il
+processo bloccato ha la precedenza ed il messaggio gli viene immediatamente
+inviato, mentre per il meccanismo di notifica tutto funziona come se la coda
+fosse rimasta vuota.
+
+Quando un messaggio arriva su una coda vuota al processo che si era registrato
+viene inviato il segnale specificato da \code{notification->sigev\_signo}, e
+la coda diventa disponibile per una ulteriore registrazione.  Questo comporta
+che se si vuole mantenere il meccanismo di notifica occorre ripetere la
+registrazione chiamando nuovamente \func{mq\_notify} all'interno del gestore
+del segnale di notifica. A differenza della situazione simile che si aveva con
+i segnali non affidabili,\footnote{l'argomento è stato affrontato in
+  \ref{sec:sig_semantics}.} questa caratteristica non configura una
+race-condition perché l'invio di un segnale avviene solo se la coda è vuota;
+pertanto se si vuole evitare di correre il rischio di perdere eventuali
+ulteriori segnali inviati nel lasso di tempo che occorre per ripetere la
+richiesta di notifica basta avere cura di eseguire questa operazione prima di
+estrarre i messaggi presenti dalla coda.
+
+L'invio del segnale di notifica avvalora alcuni campi di informazione
+restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in
+fig.~\ref{fig:sig_siginfo_t}). In particolare \var{si\_pid} viene impostato al
+valore del \acr{pid} del processo che ha emesso il segnale, \var{si\_uid}
+all'userid effettivo, \var{si\_code} a \const{SI\_MESGQ}, e \var{si\_errno} a
+0. Questo ci dice che, se si effettua la ricezione dei messaggi usando
+esclusivamente il meccanismo di notifica, è possibile ottenere le informazioni
+sul processo che ha inserito un messaggio usando un gestore per il segnale in
+forma estesa\footnote{di nuovo si faccia riferimento a quanto detto al
+  proposito in sez.~\ref{sec:sig_sigaction} e sez.~\ref{sec:sig_real_time}.}
+
 
 
 \subsection{Semafori}
@@ -4193,9 +3752,18 @@ implementa solo a livello di thread e non di processi.\footnote{questo
   sincronizzazione fra processi diversi.} Esiste però anche una libreria
 realizzata da Konstantin Knizhnik, che reimplementa l'interfaccia POSIX usando
 i semafori di SysV IPC, e che non vale comunque la pena di usare visto che i
-problemi sottolineati in \secref{sec:ipc_sysv_sem} rimangono, anche se
+problemi sottolineati in sez.~\ref{sec:ipc_sysv_sem} rimangono, anche se
 mascherati.
 
+In realtà a partire dal kernel 2.5.7 è stato introdotto un meccanismo di
+sincronizzazione completamente nuovo, basato sui cosiddetti
+\textit{futex}\footnote{la sigla sta per \textit{faxt user mode mutex}.}, con
+il quale dovrebbe essere possibile implementare una versione nativa dei
+semafori; esso è già stato usato con successo per reimplementare in maniera
+più efficiente tutte le direttive di sincronizzazione previste per i thread
+POSIX. L'interfaccia corrente è stata stabilizzata a partire dal kernel
+2.5.40.
+
 
 
 
@@ -4203,34 +3771,178 @@ mascherati.
 \label{sec:ipc_posix_shm}
 
 La memoria condivisa è l'unico degli oggetti di IPC POSIX già presente nel
-kernel ufficiale. Per poterla utilizzare occorre abilitare il filesystem
-\texttt{tmpfs}, uno speciale filesystem che mantiene tutti i suoi contenuti in
-memoria,\footnote{il filesystem \texttt{tmpfs} è diverso da un normale RAM
-  disk, anch'esso disponibile attraverso il filesystem \texttt{ramfs}, proprio
-  perché realizza una interfaccia utilizzabile anche per la memoria condivisa;
-  esso infatti non ha dimensione fissa, ed usa direttamente la cache interna
-  del kernel (viene usato anche per la SysV shared memory). In più i suoi
-  contenuti, essendo trattati direttamente dalla memoria
-  virtuale\index{memoria virtuale} e possono essere salvati sullo swap
-  automaticamente.} abilitando l'opzione \texttt{CONFIG\_TMPFS} in fase di
-compilazione del kernel, e montando il filesystem aggiungendo una riga tipo:
+kernel ufficiale; in realtà il supporto a questo tipo di oggetti è realizzato
+attraverso il filesystem \texttt{tmpfs}, uno speciale filesystem che mantiene
+tutti i suoi contenuti in memoria,\footnote{il filesystem \texttt{tmpfs} è
+  diverso da un normale RAM disk, anch'esso disponibile attraverso il
+  filesystem \texttt{ramfs}, proprio perché realizza una interfaccia
+  utilizzabile anche per la memoria condivisa; esso infatti non ha dimensione
+  fissa, ed usa direttamente la cache interna del kernel (che viene usata
+  anche per la shared memory in stile SysV). In più i suoi contenuti, essendo
+  trattati direttamente dalla memoria virtuale\index{memoria virtuale} possono
+  essere salvati sullo swap automaticamente.} che viene attivato abilitando
+l'opzione \texttt{CONFIG\_TMPFS} in fase di compilazione del kernel.
+
+
+Per potere utilizzare l'interfaccia POSIX per le code di messaggi le
+\acr{glibc}\footnote{le funzioni sono state introdotte con le glibc-2.2.}
+richiedono di compilare i programmi con l'opzione \code{-lrt}; inoltre è
+necessario che in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs};
+questo di norma viene eseguita aggiungendo una riga tipo:
 \begin{verbatim}
 tmpfs   /dev/shm        tmpfs   defaults        0      0
 \end{verbatim}
-ad \file{/etc/fstab}, oppure dove si preferisce con un comando del
-tipo:\footnote{il filesystem riconosce, oltre quelle mostrate, le opzioni
-  \texttt{uid} e \texttt{gid} che identificano rispettivamente utente e gruppo
-  cui assegnarne la titolarità, e \texttt{nr\_blocks} che permette di
-  specificarne la dimensione in blocchi, cioè in multipli di
-  \const{PAGECACHE\_SIZE}.}
+ad \file{/etc/fstab}. In realtà si può montare un filesystem \texttt{tmpfs}
+dove si vuole, per usarlo come RAM disk, con un comando del tipo:
 \begin{verbatim}
-mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs
+mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs
 \end{verbatim}
 
+Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e
+\texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne
+la titolarità, e \texttt{nr\_blocks} che permette di specificarne la
+dimensione in blocchi, cioè in multipli di \const{PAGECACHE\_SIZE} che in
+questo caso è l'unità di allocazione elementare.
+
+La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed
+eventualmente di crearlo se non esiste ancora, è \funcd{shm\_open}; il suo
+prototipo è:
+\begin{prototype}{mqueue.h}
+{int shm\_open(const char *name, int oflag, mode\_t mode)}
+
+Apre un segmento di memoria condivisa.
+  
+\bodydesc{La funzione restituisce un file descriptor positivo in caso di
+  successo e -1 in caso di errore; nel quel caso \var{errno} assumerà gli
+  stessi valori riportati da \func{open}.}
+\end{prototype}
+
+La funzione apre un segmento di memoria condivisa identificato dal nome
+\param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo nome
+può essere specificato in forma standard solo facendolo iniziare per \file{/}
+e senza ulteriori \file{/}, Linux supporta comunque nomi generici, che
+verranno intepretati prendendo come radice \file{/dev/shm}.\footnote{occorre
+  pertanto evitare di specificare qualcosa del tipo \file{/dev/shm/nome}
+  all'interno di \param{name}, perché questo comporta, da parte delle routine
+  di libereria, il tentativo di accedere a \file{/dev/shm/dev/shm/nome}.}
+
+La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
+possono essere specificati per \param{oflag}, che deve essere specificato come
+maschera binaria comprendente almeno uno dei due valori \const{O\_RDONLY} e
+\const{O\_RDWR}; i valori possibili per i vari bit sono quelli visti in
+tab.~\ref{tab:file_open_flags} dei quali però \func{shm\_open} riconosce solo
+i seguenti:
+\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{O\_RDONLY}] Apre il file descriptor associato al segmento di
+  memoria condivisa per l'accesso in sola lettura.
+\item[\const{O\_RDWR}] Apre il file descriptor associato al segmento di
+  memoria condivisa per l'accesso in lettura e scrittura.
+\item[\const{O\_CREAT}] Necessario qualora si debba creare il segmento di
+  memoria condivisa se esso non esiste; in questo caso viene usato il valore
+  di \param{mode} per impostare i permessi, che devono essere compatibili con
+  le modalità con cui si è aperto il file.
+\item[\const{O\_EXCL}] Se usato insieme a \const{O\_CREAT} fa fallire la
+  chiamata a \func{shm\_open} se il segmento esiste già, altrimenti esegue la
+  creazione atomicamente.
+\item[\const{O\_TRUNC}] Se il segmento di memoria condivisa esiste già, ne
+  tronca le dimensioni a 0 byte.
+\end{basedescript}
+
+In caso di successo la funzione restituisce un file descriptor associato al
+segmento di memoria condiviso con le stesse modalità di
+\func{open}\footnote{in realtà, come accennato, \func{shm\_open} è un semplice
+  wrapper per \func{open}, usare direttamente quest'ultima avrebbe lo stesso
+  effetto.}  viste in sez.~\ref{sec:file_open}; in particolare viene impostato
+il flag \const{FD\_CLOEXEC}.  Chiamate effettuate da diversi processi usando
+lo stesso nome, restituiranno file descriptor associati allo stesso segmento
+(così come, nel caso di file di dati, essi sono associati allo stesso inode).
+In questo modo è possibile effettuare una chiamata ad \func{mmap} sul file
+descriptor restituito da \func{shm\_open} ed i processi vedranno lo stesso
+segmento di memoria condivisa.
+
+Quando il nome non esiste il segmento può essere creato specificando
+\const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file)
+lunghezza nulla. Dato che un segmento di lunghezza nulla è di scarsa utilità,
+per impostarne la dimensione si deve usare \func{ftruncate} (vedi
+sez.~\ref{sec:file_file_size}), prima di mapparlo in memoria con \func{mmap}.
+Si tenga presente che una volta chiamata \func{mmap} si può chiudere il file
+descriptor (con \func{close}), senza che la mappatura ne risenta.
+
+
+Come per i file, quando si vuole effettivamente rimuovere segmento di memoria
+condivisa, occorre usare la funzione \funcd{shm\_unlink}, il cui prototipo è:
+\begin{prototype}{mqueue.h}
+{int shm\_unlink(const char *name)}
+
+Rimuove un segmento di memoria condivisa.
+  
+\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+  errore; nel quel caso \var{errno} assumerà gli stessi valori riportati da
+  \func{unlink}.}
+\end{prototype}
+
+La funzione è del tutto analoga ad \func{unlink}, e si limita a cancellare il
+nome del segmento da \file{/dev/shm}, senza nessun effetto né sui file
+descriptor precedentemente aperti con \func{shm\_open}, né sui segmenti già
+mappati in memoria; questi verranno cancellati automaticamente dal sistema
+solo con le rispettive chiamate a \func{close} e \func{munmap}.  Una volta
+eseguita questa funzione però, qualora si richieda l'apertura di un segmento
+con lo stesso nome, la chiamata a \func{shm\_open} fallirà, a meno di non aver
+usato \const{O\_CREAT}, in quest'ultimo caso comunque si otterrà un file
+descriptor che fa riferimento ad un segmento distinto da eventuali precedenti.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MemShared.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni di gestione dei segmenti di memoria
+    condivisa POSIX.}
+  \label{fig:ipc_posix_shmmem}
+\end{figure}
+
+Come esempio per l'uso di queste funzioni vediamo come è possibile riscrivere
+una interfaccia semplificata analoga a quella vista in
+fig.~\ref{fig:ipc_sysv_shm_func} per la memoria condivisa in stile SysV. Il
+codice, riportato in fig.~\ref{fig:ipc_posix_shmmem}, è sempre contenuto nel
+file \file{SharedMem.c} dei sorgenti allegati.
+
+La prima funzione (\texttt{\small 1--24}) è \func{CreateShm} che, dato un nome
+nell'argomento \var{name} crea un nuovo segmento di memoria condivisa,
+accessibile in lettura e scrittura, e ne restituisce l'indirizzo. Anzitutto si
+definiscono (\texttt{\small 8}) i flag per la successiva (\texttt{\small 9})
+chiamata a \func{shm\_open}, che apre il segmento in lettura e scrittura
+(creandolo se non esiste, ed uscendo in caso contrario) assegnandogli sul
+filesystem i permessi specificati dall'argomento \var{perm}. In caso di errore
+(\texttt{\small 10--12}) si restituisce un puntatore nullo, altrimenti si
+prosegue impostando (\texttt{\small 14}) la dimensione del segmento con
+\func{ftruncate}. Di nuovo (\texttt{\small 15--16}) si esce immediatamente
+restituendo un puntatore nullo in caso di errore. Poi si passa (\texttt{\small
+  18}) a mappare in memoria il segmento con \func{mmap} specificando dei
+diritti di accesso corrispondenti alla modalità di apertura.  Di nuovo si
+restituisce (\texttt{\small 19--21}) un puntatore nullo in caso di errore,
+altrimenti si inizializza (\texttt{\small 22}) il contenuto del segmento al
+valore specificato dall'argomento \var{fill} con \func{memset}, e se ne
+restituisce (\texttt{\small 23}) l'indirizzo.
+
+La seconda funzione (\texttt{\small 25--40}) è \func{FindShm} che trova un
+segmento di memoria condiviso già esistente, restituendone l'indirizzo. In
+questo caso si apre (\texttt{\small 31}) il segmento con \func{shm\_open}
+richiedendo che il segmento sia già esistente, in caso di errore
+(\texttt{\small 31--33}) si ritorna immediatamente un puntatore nullo.
+Ottenuto il file descriptor del segmento lo si mappa (\texttt{\small 35}) in
+memoria con \func{mmap}, restituendo (\texttt{\small 36--38}) un puntatore
+nullo in caso di errore, o l'indirizzo (\texttt{\small 39}) dello stesso in
+caso di successo.
+
+La terza funzione (\texttt{\small 40--45}) è \func{RemoveShm}, e serve a
+cancellare un segmento di memoria condivisa. Dato che al contrario di quanto
+avveniva con i segmenti del SysV IPC gli oggetti allocati nel kernel vengono
+rilasciati automaticamente quando nessuna li usa più, tutto quello che c'è da
+fare (\texttt{\small 44}) in questo caso è chiamare \func{shm\_unlink},
+retituendo al chiamante il valore di ritorno.
 
- la memoria
-condivisa è trattata come un filesystem separato, con tutte le caratteristiche
-di un qualunque filesystem,
 
 
 %%% Local Variables: