Ripulitura dell'HTML, tanto per vedere se ci capisco qualcosa di XHTML & C.
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 977f9f009beac97df2e29d5fdd1a8724472dc601..56caf92637cb7f867130c134554b638387f9f3bf 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -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).
 
@@ -150,7 +150,7 @@ possa reinviarlo al browser che ha effettuato la richiesta, che in questo modo
 è in grado di visualizzarlo opportunamente.
 
 Per realizzare quanto voluto useremo in sequenza i programmi \cmd{barcode} e
-\cmd{gs}, il primo infatti è in grado di generare immagini postscript di
+\cmd{gs}, il primo infatti è in grado di generare immagini PostScript di
 codici a barre corrispondenti ad una qualunque stringa, mentre il secondo
 serve per poter effettuare la conversione della stessa immagine in formato
 JPEG. Usando una pipe potremo inviare l'output del primo sull'input del
@@ -190,55 +190,7 @@ 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} 
@@ -259,7 +211,7 @@ richiesta.\footnote{la funzione \func{WriteMess} non 
 Una volta create le pipe, il programma può creare (\texttt{\small 13-17}) il
 primo processo figlio, che si incaricherà (\texttt{\small 19--25}) di eseguire
 \cmd{barcode}. Quest'ultimo legge dallo standard input una stringa di
-caratteri, la converte nell'immagine postscript del codice a barre ad essa
+caratteri, la converte nell'immagine PostScript del codice a barre ad essa
 corrispondente, e poi scrive il risultato direttamente sullo standard output.
 
 Per poter utilizzare queste caratteristiche prima di eseguire \cmd{barcode} si
@@ -268,7 +220,7 @@ ne collega (\texttt{\small 21}) il capo in lettura allo standard input, usando
 \func{dup2}. Si ricordi che invocando \func{dup2} il secondo file, qualora
 risulti aperto, viene, come nel caso corrente, chiuso prima di effettuare la
 duplicazione. Allo stesso modo, dato che \cmd{barcode} scrive l'immagine
-postscript del codice a barre sullo standard output, per poter effettuare una
+PostScript del codice a barre sullo standard output, per poter effettuare una
 ulteriore redirezione il capo in lettura della seconda pipe viene chiuso
 (\texttt{\small 22}) mentre il capo in scrittura viene collegato allo standard
 output (\texttt{\small 23}).
@@ -276,7 +228,7 @@ output (\texttt{\small 23}).
 In questo modo all'esecuzione (\texttt{\small 25}) di \cmd{barcode} (cui si
 passa in \var{size} la dimensione della pagina per l'immagine) quest'ultimo
 leggerà dalla prima pipe la stringa da codificare che gli sarà inviata dal
-padre, e scriverà l'immagine postscript del codice a barre sulla seconda.
+padre, e scriverà l'immagine PostScript del codice a barre sulla seconda.
 
 Al contempo una volta lanciato il primo figlio, il processo padre prima chiude
 (\texttt{\small 26}) il capo inutilizzato della prima pipe (quello in input) e
@@ -287,11 +239,11 @@ definitivamente chiusa (\texttt{\small 28}), si attende poi (\texttt{\small
   29}) che l'esecuzione di \cmd{barcode} sia completata.
 
 Alla conclusione della sua esecuzione \cmd{barcode} avrà inviato l'immagine
-postscript del codice a barre sul capo in scrittura della seconda pipe; a
+PostScript del codice a barre sul capo in scrittura della seconda pipe; a
 questo punto si può eseguire la seconda conversione, da PS a JPEG, usando il
 programma \cmd{gs}. Per questo si crea (\texttt{\small 30--34}) un secondo
 processo figlio, che poi (\texttt{\small 35--42}) eseguirà questo programma
-leggendo l'immagine postscript creata da \cmd{barcode} dallo standard input,
+leggendo l'immagine PostScript creata da \cmd{barcode} dallo standard input,
 per convertirla in JPEG.
 
 Per fare tutto ciò anzitutto si chiude (\texttt{\small 37}) il capo in
@@ -349,7 +301,7 @@ 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 inode\index{inode}, e viene sempre aperto in modalità
+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 è:
@@ -372,8 +324,8 @@ precedente: il programma mostrato in \figref{fig:ipc_barcodepage_code} per
 quanto funzionante, è (volutamente) codificato in maniera piuttosto complessa,
 inoltre nella pratica sconta un problema di \cmd{gs} che non è in
 grado\footnote{nella versione GNU Ghostscript 6.53 (2002-02-13).} di
-riconoscere correttamente l'encapsulated postscript, per cui deve essere usato
-il postscript e tutte le volte viene generata una pagina intera, invece che
+riconoscere correttamente l'Encapsulated PostScript, per cui deve essere usato
+il PostScript e tutte le volte viene generata una pagina intera, invece che
 una immagine delle dimensioni corrispondenti al codice a barre.
 
 Se si vuole generare una immagine di dimensioni appropriate si deve usare un
@@ -423,37 +375,7 @@ 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 stout */ 
-    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}.}
@@ -594,59 +516,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/italia";
-    char **fortune;
-    char line[80];
-    int fifo_server, fifo_client;
-    int nread;
-    ...
-    if (n==0) usage();          /* if no pool depth exit printing usage info */
-    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
-    Signal(SIGINT, HandSIGTERM);
-    Signal(SIGQUIT, HandSIGTERM);
-    i = FortuneParse(fortunefilename, fortune, n);          /* parse phrases */
-    if (mkfifo(fifoname, 0622)) {  /* create well known fifo if does't exist */
-        if (errno!=EEXIST) {
-            perror("Cannot create well known fifo");
-            exit(1);
-        }
-    }
-    /* open fifo two times to avoid EOF */
-    fifo_server = open(fifoname, O_RDONLY);
-    if (fifo_server < 0) {
-        perror("Cannot open read only well known fifo");
-        exit(1);
-    }
-    if (open(fifoname, O_WRONLY) < 0) {                        
-        perror("Cannot open write only well known fifo");
-        exit(1);
-    }
-    /* Main body: loop over requests */
-    while (1) {
-        nread = read(fifo_server, line, 79);                 /* read request */
-        if (nread < 0) {
-            perror("Read Error");
-            exit(1);
-        }
-        line[nread] = 0;                       /* terminate fifo name string */
-        n = random() % i;                             /* select random value */
-        fifo_client = open(line, O_WRONLY);              /* open client fifo */
-        if (fifo_client < 0) {
-            perror("Cannot open");
-            exit(1);
-        }
-        nread = write(fifo_client,                           /* write phrase */
-                      fortune[n], strlen(fortune[n])+1);
-        close(fifo_client);                             /* close client fifo */
-    }
-}
-    \end{lstlisting}
+    \includecodesample{listati/FortuneServer.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del server di \textit{fortunes}
@@ -676,41 +546,45 @@ qualora si riscontri un errore il server uscir
 in cui la funzione \func{mkfifo} fallisce per la precedente esistenza della
 fifo).
 
-Una volta che si è certi che la fifo di ascolto esiste si procede
-(\texttt{\small 23--32}) alla sua apertura. Questo viene fatto due volte
-per evitare di dover gestire all'interno del ciclo principale il caso in cui
-il server è in ascolto ma non ci sono client che effettuano richieste.
-Si ricordi infatti che quando una fifo è aperta solo dal capo in lettura,
-l'esecuzione di \func{read} ritorna con zero byte (si ha cioè una condizione
-di end-of-file).
+Una volta che si è certi che la fifo di ascolto esiste la procedura di
+inizializzazione è completata. A questo punto si può chiamare (\texttt{\small
+  23}) la funzione \func{daemon} per far proseguire l'esecuzione del programma
+in background come demone.  Si può quindi procedere (\texttt{\small 24--33})
+alla apertura della fifo: si noti che questo viene fatto due volte, prima in
+lettura e poi in scrittura, per evitare di dover gestire all'interno del ciclo
+principale il caso in cui il server è in ascolto ma non ci sono client che
+effettuano richieste.  Si ricordi infatti che quando una fifo è aperta solo
+dal capo in lettura, l'esecuzione di \func{read} ritorna con zero byte (si ha
+cioè una condizione di end-of-file).
 
 Nel nostro caso la prima apertura si bloccherà fintanto che un qualunque
 client non apre a sua volta la fifo nota in scrittura per effettuare la sua
 richiesta. Pertanto all'inizio non ci sono problemi, il client però, una volta
 ricevuta la risposta, uscirà, chiudendo tutti i file aperti, compresa la fifo.
 A questo punto il server resta (se non ci sono altri client che stanno
-effettuando richieste) con la fifo chiusa sul lato in lettura e a questo punto
-\func{read} non si bloccherà in attesa di input, ma ritornerà in continuazione
-restituendo un end-of-file.\footnote{Si è usata questa tecnica per
-  compatibilità, Linux infatti supporta l'apertura delle fifo in
-  lettura/scrittura, per cui si sarebbe potuto effettuare una singola apertura
-  con \const{O\_RDWR}, la doppia apertura comunque ha il vantaggio che non si
-  può scrivere per errore sul capo aperto in sola lettura.}
+effettuando richieste) con la fifo chiusa sul lato in lettura, ed in questo
+stato la funzione \func{read} non si bloccherà in attesa di input, ma
+ritornerà in continuazione, restituendo un end-of-file.\footnote{Si è usata
+  questa tecnica per compatibilità, Linux infatti supporta l'apertura delle
+  fifo in lettura/scrittura, per cui si sarebbe potuto effettuare una singola
+  apertura con \const{O\_RDWR}, la doppia apertura comunque ha il vantaggio
+  che non si può scrivere per errore sul capo aperto in sola lettura.}
 
 Per questo motivo, dopo aver eseguito l'apertura in lettura (\texttt{\small
-  24--28}),\footnote{di solito si effettua l'apertura del capo in lettura in
-  modalità non bloccante, per evitare il rischio di uno stallo (se nessuno
-  apre la fifo in scrittura il processo non ritornerà mai dalla \func{open})
-  che nel nostro caso non esiste, mentre è necessario potersi bloccare in
-  lettura in attesa di una richiesta.} si esegue una seconda apertura in
-scrittura (\texttt{\small 29--32}), scartando il relativo file descriptor che
-non sarà mai usato, ma lasciando la fifo comunque aperta anche in scrittura,
-cosicché le successive possano bloccarsi.
+  24--28}),\footnote{di solito si effettua l'apertura del capo in lettura di
+  una fifo in modalità non bloccante, per evitare il rischio di uno stallo: se
+  infatti nessuno apre la fifo in scrittura il processo non ritornerà mai
+  dalla \func{open}. Nel nostro caso questo rischio non esiste, mentre è
+  necessario potersi bloccare in lettura in attesa di una richiesta.} si
+esegue una seconda apertura in scrittura (\texttt{\small 29--32}), scartando
+il relativo file descriptor, che non sarà mai usato, in questo modo però la
+fifo resta comunque aperta anche in scrittura, cosicché le successive chiamate
+a \func{read} possono bloccarsi.
 
 A questo punto si può entrare nel ciclo principale del programma che fornisce
-le risposte ai client (\texttt{\small 34--50}), che viene eseguito
+le risposte ai client (\texttt{\small 34--50}); questo viene eseguito
 indefinitamente (l'uscita del server viene effettuata inviando un segnale, in
-modo da passare attraverso la routine di chiusura che cancella la fifo). 
+modo da passare attraverso la routine di chiusura che cancella la fifo).
 
 Il server è progettato per accettare come richieste dai client delle stringhe
 che contengono il nome della fifo sulla quale deve essere inviata la risposta.
@@ -719,9 +593,9 @@ richiesta dalla fifo nota (che a questo punto si bloccher
 non ci sono richieste). Dopo di che, una volta terminata la stringa
 (\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero casuale per
 ricavare la frase da inviare, si procederà (\texttt{\small 42--46})
-all'apertura della fifo per la risposta, che \texttt{\small 47--48}) poi vi
+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ù. 
+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
@@ -732,44 +606,7 @@ principale del programma e le definizioni delle variabili. Il codice completo
 \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}
@@ -802,6 +639,62 @@ la richiesta, se non si fosse fatto cos
 quanto senza la richiesta, il server non avrebbe potuto aprirne il capo in
 scrittura e l'apertura si sarebbe bloccata indefinitamente.
 
+Verifichiamo allora il comportamento dei nostri programmi, in questo, come in
+altri esempi precedenti, si fa uso delle varie funzioni di servizio, che sono
+state raccolte nella libreria \file{libgapil.so}, per poter usare quest'ultima
+occorrerà definire la speciale variabile di ambiente \code{LD\_LIBRARY\_PATH}
+in modo che il linker dinamico possa accedervi.
+
+In generale questa variabile indica il pathname della directory contenente la
+libreria. Nell'ipotesi (che daremo sempre per verificata) che si facciano le
+prove direttamente nella directory dei sorgenti (dove di norma vengono creati
+sia i programmi che la libreria), il comando da dare sarà \code{export
+  LD\_LIBRARY\_PATH=./}; a questo punto potremo lanciare il server, facendogli
+leggere una decina di frasi, con:
+\begin{verbatim}
+[piccardi@gont sources]$ ./fortuned -n10
+\end{verbatim}
+
+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}):
+\begin{verbatim}
+[piccardi@gont sources]$ ps aux
+...
+piccardi 27489  0.0  0.0  1204  356 ?        S    01:06   0:00 ./fortuned -n10
+piccardi 27492  3.0  0.1  2492  764 pts/2    R    01:08   0:00 ps aux
+\end{verbatim}%$
+e si potrà verificare anche che in \file{/tmp} è stata creata la fifo di
+ascolto \file{fortune.fifo}. A questo punto potremo interrogare il server con
+il programma client; otterremo così:
+\begin{verbatim}
+[piccardi@gont sources]$ ./fortune
+Linux ext2fs has been stable for a long time, now it's time to break it
+        -- Linuxkongreß '95 in Berlin
+[piccardi@gont sources]$ ./fortune
+Let's call it an accidental feature.
+        --Larry Wall
+[piccardi@gont sources]$ ./fortune
+.........    Escape the 'Gates' of Hell
+  `:::'                  .......  ......
+   :::  *                  `::.    ::'
+   ::: .::  .:.::.  .:: .::  `::. :'
+   :::  ::   ::  ::  ::  ::    :::.
+   ::: .::. .::  ::.  `::::. .:'  ::.
+...:::.....................::'   .::::..
+        -- William E. Roadcap
+[piccardi@gont sources]$ ./fortune
+Linux ext2fs has been stable for a long time, now it's time to break it
+        -- Linuxkongreß '95 in Berlin
+\end{verbatim}%$
+e ripetendo varie volte il comando otterremo, in ordine casuale, le dieci
+frasi tenute in memoria dal server.
+
+Infine per chiudere il server basterà inviare un segnale di terminazione con
+\code{killall fortuned} e potremo verificare che il gestore del segnale ha
+anche correttamente cancellato la fifo di ascolto da \file{/tmp}.
+
 Benché il nostro sistema client-server funzioni, la sua struttura è piuttosto
 complessa e continua ad avere vari inconvenienti\footnote{lo stesso Stevens,
   che esamina questa architettura in \cite{APUE}, nota come sia impossibile
@@ -941,18 +834,7 @@ mantiene varie propriet
 \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
@@ -1133,7 +1015,7 @@ Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino
   kernel, andando a modificarne la definizione nei relativi header file.  A
   partire dal kernel 2.4.x è possibile cambiare questi valori a sistema attivo
   scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di
-  \file{/proc/sys/kernel} o con l'uso di \texttt{syscntl}.} e per ciascuno di
+  \file{/proc/sys/kernel} o con l'uso di \func{sysctl}.} e per ciascuno di
 essi viene mantenuto in \var{seq} un numero di sequenza progressivo che viene
 incrementato di uno ogni volta che l'oggetto viene cancellato. Quando
 l'oggetto viene creato usando uno spazio che era già stato utilizzato in
@@ -1149,41 +1031,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
@@ -1323,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
-modificare questi limiti attraverso l'uso di \func{syscntl} o scrivendo nei
+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/}.
 
 
@@ -1354,30 +1202,16 @@ 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{msgid\_ds}, associata a ciascuna coda di
+  \caption{La struttura \structd{msqid\_ds}, associata a ciascuna coda di
     messaggi.}
-  \label{fig:ipc_msgid_ds}
+  \label{fig:ipc_msqid_ds}
 \end{figure}
 
 A ciascuna coda è associata una struttura \struct{msgid\_ds}, la cui
-definizione, è riportata in \secref{fig:ipc_msgid_ds}. In questa struttura il
+definizione, è riportata in \secref{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
@@ -1385,7 +1219,7 @@ coda.\footnote{come accennato questo vale fino ai kernel della serie 2.2.x,
   sia una differenza con i campi mostrati nello schema di
   \figref{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_msgid_ds} sono elencati i
+  struttura usata nel kernel.} In \figref{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.
@@ -1394,7 +1228,7 @@ Quando si crea una nuova coda con \func{msgget} questa struttura viene
 inizializzata, in particolare il campo \var{msg\_perm} viene inizializzato
 come illustrato in \secref{sec:ipc_sysv_access_control}, per quanto riguarda
 gli altri campi invece:
-\begin{itemize}
+\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
@@ -1413,7 +1247,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}
@@ -1534,12 +1368,7 @@ dovr
 \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
@@ -1631,7 +1460,7 @@ una scansione della struttura mostrata in \figref{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*}
+\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. 
 \item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui
@@ -1640,7 +1469,7 @@ coda, 
 \item se \param{msgtyp} è negativo viene estratto il primo fra i messaggi con
   il valore più basso del tipo, fra tutti quelli il cui tipo ha un valore
   inferiore al valore assoluto di \param{msgtyp}.
-\end{itemize*}
+\end{itemize}
 
 Il valore di \param{msgflg} permette di controllare il comportamento della
 funzione, esso può essere nullo o una maschera binaria composta da uno o più
@@ -1694,56 +1523,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;                              /* fortune 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 */
-    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}
@@ -1774,7 +1555,7 @@ in \var{n} il numero di frasi da leggere specificato a linea di comando ed in
 server, viene prima controllato (\texttt{\small 22}) il numero di frasi
 richieste abbia senso (cioè sia maggiore di zero), le quali poi
 (\texttt{\small 23}) vengono lette nel vettore in memoria con la stessa
-funzione \code{FortuneParse()} usata anche per il server basato sulle fifo.
+funzione \code{FortuneParse} usata anche per il server basato sulle fifo.
 
 Una volta inizializzato il vettore di stringhe coi messaggi presi dal file
 delle \textit{fortune} si procede (\texttt{\small 25}) con la generazione di
@@ -1784,56 +1565,40 @@ creazione della stessa (si noti come si sia chiamata \func{msgget} con un
 valore opportuno per l'argomento \param{flag}), avendo cura di abortire il
 programma (\texttt{\small 27--29}) in caso di errore.
 
-Finita la fase di inizializzazione il server esegue in permanenza il ciclo
-principale (\texttt{\small 32--41}). Questo inizia (\texttt{\small 33}) con il
-porsi in attesa di un messaggio di richiesta da parte di un client; si noti
-infatti come \func{msgrcv} richieda un messaggio con \var{mtype} uguale a 1:
-questo è il valore usato per le richieste dato che corrisponde al \acr{pid} di
-\cmd{init}, che non può essere un client. L'uso del flag \const{MSG\_NOERROR}
-è solo per sicurezza, dato che i messaggi di richiesta sono di dimensione
-fissa (e contengono solo il \acr{pid} del client).
+Finita la fase di inizializzazione il server prima (\texttt{\small 32}) chiama
+la funzione \func{daemon} per andare in background e poi esegue in permanenza
+il ciclo principale (\texttt{\small 33--40}). Questo inizia (\texttt{\small
+  34}) con il porsi in attesa di un messaggio di richiesta da parte di un
+client; si noti infatti come \func{msgrcv} richieda un messaggio con
+\var{mtype} uguale a 1: questo è il valore usato per le richieste dato che
+corrisponde al \acr{pid} di \cmd{init}, che non può essere un client. L'uso
+del flag \const{MSG\_NOERROR} è solo per sicurezza, dato che i messaggi di
+richiesta sono di dimensione fissa (e contengono solo il \acr{pid} del
+client).
 
 Se non sono presenti messaggi di richiesta \func{msgrcv} si bloccherà,
 ritornando soltanto in corrispondenza dell'arrivo sulla coda di un messaggio
 di richiesta da parte di un client, in tal caso il ciclo prosegue
-(\texttt{\small 34}) selezionando una frase a caso, copiandola (\texttt{\small
-  35}) nella struttura \var{msgbuf\_write} usata per la risposta e
-calcolandone (\texttt{\small 36}) la dimensione.
+(\texttt{\small 35}) selezionando una frase a caso, copiandola (\texttt{\small
+  36}) nella struttura \var{msgbuf\_write} usata per la risposta e
+calcolandone (\texttt{\small 37}) la dimensione.
 
 Per poter permettere a ciascun client di ricevere solo la risposta indirizzata
-a lui il tipo del messaggio in uscita viene inizializzato (\texttt{\small 37})
+a lui il tipo del messaggio in uscita viene inizializzato (\texttt{\small 38})
 al valore del \acr{pid} del client ricevuto nel messaggio di richiesta.
-L'ultimo passo del ciclo (\texttt{\small 38}) è inviare sulla coda il
+L'ultimo passo del ciclo (\texttt{\small 39}) è inviare sulla coda il
 messaggio di risposta. Si tenga conto che se la coda è piena anche questa
 funzione potrà bloccarsi fintanto che non venga liberato dello spazio.
 
 Si noti che il programma può terminare solo grazie ad una interruzione da
-parte di un segnale; in tal caso verrà eseguito il gestore
-\code{HandSIGTERM}, che semplicemente si limita a cancellare la coda
-(\texttt{\small 44}) ed ad uscire (\texttt{\small 45}).
+parte di un segnale; in tal caso verrà eseguito (\texttt{\small 45--48}) il
+gestore \code{HandSIGTERM}, che semplicemente si limita a cancellare la coda
+(\texttt{\small 46}) ed ad uscire (\texttt{\small 47}).
 
 \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}
@@ -1868,6 +1633,43 @@ tipo corrispondente al valore del \acr{pid} inviato nella richiesta. L'ultimo
 passo (\texttt{\small 17}) prima di uscire è quello di stampare a video il
 messaggio ricevuto.
  
+Proviamo allora il nostro nuovo sistema, al solito occorre definire
+\code{LD\_LIBRAY\_PATH} per accedere alla libreria \file{libgapil.so}, dopo di
+che, in maniera del tutto analoga a quanto fatto con il programma che usa le
+fifo, potremo far partire il server con:
+\begin{verbatim}
+[piccardi@gont sources]$ ./mqfortuned -n10
+\end{verbatim}%$
+come nel caso precedente, avendo eseguito il server in background, il comando
+ritornerà immediatamente; potremo però verificare con \cmd{ps} che il
+programma è effettivamente in esecuzione, e che ha creato una coda di
+messaggi:
+\begin{verbatim}
+[piccardi@gont sources]$ ipcs
+
+------ Shared Memory Segments --------
+key        shmid      owner      perms      bytes      nattch     status      
+
+------ Semaphore Arrays --------
+key        semid      owner      perms      nsems     
+
+------ Message Queues --------
+key        msqid      owner      perms      used-bytes   messages    
+0x0102dc6a 0          piccardi   666        0            0           
+\end{verbatim}
+a questo punto potremo usare il client per ottenere le nostre frasi:
+\begin{verbatim}
+[piccardi@gont sources]$ ./mqfortune
+Linux ext2fs has been stable for a long time, now it's time to break it
+        -- Linuxkongreß '95 in Berlin
+[piccardi@gont sources]$ ./mqfortune
+Let's call it an accidental feature.
+        --Larry Wall
+\end{verbatim}
+con un risultato del tutto equivalente al precedente. Infine potremo chiudere
+il server inviando il segnale di terminazione con il comando \code{killall
+  mqfortuned} verificando che effettivamente la coda di messaggi viene rimossa.
+
 Benché funzionante questa architettura risente dello stesso inconveniente
 visto anche nel caso del precedente server basato sulle fifo; se il client
 viene interrotto dopo l'invio del messaggio di richiesta e prima della lettura
@@ -1986,15 +1788,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
@@ -2036,14 +1830,7 @@ 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
@@ -2133,15 +1920,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}
@@ -2287,14 +2066,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
@@ -2470,64 +2242,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);
-}
-    \end{lstlisting}
+    \includecodesample{listati/Mutex.c}
   \end{minipage} 
   \normalsize 
   \caption{Il codice delle funzioni che permettono di creare o recuperare
@@ -2535,58 +2250,65 @@ int MutexUnlock(int sem_id)
   \label{fig:ipc_mutex_create}
 \end{figure}
 
-La prima funzione (\texttt{\small 1--17}) è \func{MutexCreate} che data una
+La prima funzione (\texttt{\small 2--15}) è \func{MutexCreate} che data una
 chiave crea il semaforo usato per il mutex e lo inizializza, restituendone
-l'identificatore. Il primo passo (\texttt{\small 8}) è chiamare \func{semget}
+l'identificatore. Il primo passo (\texttt{\small 6}) è chiamare \func{semget}
 con \const{IPC\_CREATE} per creare il semaforo qualora non esista,
 assegnandogli i privilegi di lettura e scrittura per tutti. In caso di errore
-(\texttt{\small 9--11}) si ritorna subito il risultato di \func{semget},
-altrimenti (\texttt{\small 12}) si inizializza il semaforo chiamando
+(\texttt{\small 7--9}) si ritorna subito il risultato di \func{semget},
+altrimenti (\texttt{\small 10}) si inizializza il semaforo chiamando
 \func{semctl} con il comando \const{SETVAL}, utilizzando l'unione
-\struct{semunion} dichiarata ed avvalorata in precedenza (\texttt{\small 6})
+\struct{semunion} dichiarata ed avvalorata in precedenza (\texttt{\small 4})
 ad 1 per significare che risorsa è libera. In caso di errore (\texttt{\small
-  13--16}) si restituisce il valore di ritorno di \func{semctl}, altrimenti si
-ritorna l'identificatore del semaforo.
+  11--13}) si restituisce il valore di ritorno di \func{semctl}, altrimenti
+(\texttt{\small 14}) si ritorna l'identificatore del semaforo.
 
-La seconda funzione (\texttt{\small 18--24}) è \func{MutexFind}, che data una
+La seconda funzione (\texttt{\small 17--20}) è \func{MutexFind}, che, data una
 chiave, restituisce l'identificatore del semaforo ad essa associato. La
-comprensione del suo funzionamento è immediata in quanto è solo un
+comprensione del suo funzionamento è immediata in quanto essa è soltanto un
 \textit{wrapper}\footnote{si chiama così una funzione usata per fare da
   \textsl{involucro} alla chiamata di un altra, usata in genere per
   semplificare un'interfaccia (come in questo caso) o per utilizzare con la
   stessa funzione diversi substrati (librerie, ecc.)  che possono fornire le
-  stesse funzionalità.} di \func{semget} per cercare l'identificatore
-associato alla chiave, restituendo direttamente il valore di ritorno della
-funzione.
+  stesse funzionalità.} di una chiamata a \func{semget} per cercare
+l'identificatore associato alla chiave, il valore di ritorno di quest'ultima
+viene passato all'indietro al chiamante.
 
-La terza funzione (\texttt{\small 25--31}) è \func{MutexRead} che, dato
-l'identificatore, restituisce il valore del mutex. Anche in questo caso la
-funzione è un \textit{wrapper} per la chiamata di \func{semctl}, questa volta
-con il comando \const{GETVAL}, che permette di restituire il valore del
-semaforo.
+La terza funzione (\texttt{\small 22--25}) è \func{MutexRead} che, dato un
+identificatore, restituisce il valore del semaforo associato al mutex. Anche
+in questo caso la funzione è un \textit{wrapper} per una chiamata a
+\func{semctl} con il comando \const{GETVAL}, che permette di restituire il
+valore del semaforo.
 
-La quarta e la quinta funzione (\texttt{\small 43--56}) sono \func{MutexLock},
+La quarta e la quinta funzione (\texttt{\small 36--44}) sono \func{MutexLock},
 e \func{MutexUnlock}, che permettono rispettivamente di bloccare e sbloccare
 il mutex. Entrambe fanno da wrapper per \func{semop}, utilizzando le due
 strutture \var{sem\_lock} e \var{sem\_unlock} definite in precedenza
-(\texttt{\small 32--42}). Si noti come per queste ultime si sia fatto uso
+(\texttt{\small 27--34}). Si noti come per queste ultime si sia fatto uso
 dell'opzione \const{SEM\_UNDO} per evitare che il semaforo resti bloccato in
 caso di terminazione imprevista del processo.
 
+L'ultima funzione (\texttt{\small 46--49}) della serie, è \func{MutexRemove},
+che rimuove il mutex. Anche in questo caso si ha un wrapper per una chiamata a
+\func{semctl} con il comando \const{IPC\_RMID}, che permette di cancellare il
+semaforo; il valore di ritorno di quest'ultima viene passato all'indietro.
+
 Chiamare \func{MutexLock} decrementa il valore del semaforo: se questo è
 libero (ha già valore 1) sarà bloccato (valore nullo), se è bloccato la
 chiamata a \func{semop} si bloccherà fintanto che la risorsa non venga
 rilasciata. Chiamando \func{MutexUnlock} il valore del semaforo sarà
-incrementato di uno, sbloccandolo qualora fosse bloccato.  Si noti che occorre
-eseguire sempre prima \func{MutexLock} e poi \func{MutexUnlock}, perché se per
-un qualche errore si esegue più volte quest'ultima il valore del semaforo
-crescerebbe oltre 1, e \func{MutexLock} non avrebbe più l'effetto aspettato
-(bloccare la risorsa quando questa è considerata libera). Si tenga presente
-che usare \func{MutexRead} per controllare il valore dei mutex prima di
-proseguire non servirebbe comunque, dato che l'operazione non sarebbe atomica.
-Vedremo in \secref{sec:ipc_posix_sem} come è possibile ottenere un'interfaccia
-analoga senza questo problemi usando il file locking\index{file!locking}.
+incrementato di uno, sbloccandolo qualora fosse bloccato.  
 
+Si noti che occorre eseguire sempre prima \func{MutexLock} e poi
+\func{MutexUnlock}, perché se per un qualche errore si esegue più volte
+quest'ultima il valore del semaforo crescerebbe oltre 1, e \func{MutexLock}
+non avrebbe più l'effetto aspettato (bloccare la risorsa quando questa è
+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
+un'interfaccia analoga a quella appena illustrata, senza incorrere in questi
+problemi, usando il file locking\index{file!locking}.
 
 
 \subsection{Memoria condivisa}
@@ -2648,18 +2370,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
@@ -2675,7 +2386,7 @@ campo \var{shm\_perm} viene inizializzato come illustrato in
 \secref{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
@@ -2689,13 +2400,15 @@ 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
 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
+\file{/proc/sys/kernel/}. 
+
+In \tabref{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. 
@@ -2752,49 +2465,64 @@ un segmento di memoria condivisa 
     \begin{errlist}
     \item[\errcode{EACCES}] Si è richiesto \const{IPC\_STAT} ma i permessi non
       consentono l'accesso in lettura al segmento.
-    \item[\errcode{EINVAL}] O \param{shmid} o \param{cmd} hanno valori non
-      validi.
+    \item[\errcode{EINVAL}] O \param{shmid} non è un identificatore valido o
+      \param{cmd} non è un comando valido.
     \item[\errcode{EIDRM}] L'argomento \param{shmid} fa riferimento ad un
       segmento che è stato cancellato.
     \item[\errcode{EPERM}] Si è specificato un comando con \const{IPC\_SET} o
       \const{IPC\_RMID} senza i permessi necessari.
-    \item[\errcode{EOVERFLOW}] L'argomento \param{shmid} fa riferimento ad un
-      segmento che è stato cancellato.
+    \item[\errcode{EOVERFLOW}] Si è tentato il comando \const{IPC\_STAT} ma il
+      valore del group-ID o dell'user-ID è troppo grande per essere
+      memorizzato nella struttura puntata dal \param{buf}.  
+    \item[\errcode{EFAULT}] L'indirizzo specificato con \param{buf} non è
+      valido.
     \end{errlist}
-  ed inoltre \errval{EFAULT}.}
+}
 \end{functions}
 
-Il comportamento della funzione dipende dal valore del comando passato
-attraverso l'argomento \param{cmd}, i valori possibili sono i seguenti:
+Il comando specificato attraverso l'argomento \param{cmd} determina i diversi
+effetti della funzione; i possibili valori che esso può assumere, ed il
+corrispondente comportamento della funzione, sono i seguenti:
+
 \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
 \item[\const{IPC\_STAT}] Legge le informazioni riguardo il segmento di memoria
   condivisa nella struttura \struct{shmid\_ds} puntata da \param{buf}. Occorre
-  avere il permesso di lettura sulla coda.
+  che il processo chiamante abbia il permesso di lettura sulla segmento.
 \item[\const{IPC\_RMID}] Marca il segmento di memoria condivisa per la
   rimozione, questo verrà cancellato effettivamente solo quando l'ultimo
   processo ad esso agganciato si sarà staccato. Questo comando può essere
   eseguito solo da un processo con user-ID effettivo corrispondente o al
-  creatore della coda, o al proprietario della coda, o all'amministratore.
+  creatore del segmento, o al proprietario del segmento, o all'amministratore.
 \item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario
   del segmento.  Per modificare i valori di \var{shm\_perm.mode},
   \var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
-  il creatore della coda, oppure l'amministratore. Compiuta l'operazione
+  il creatore del segmento, oppure l'amministratore. Compiuta l'operazione
   aggiorna anche il valore del campo \var{shm\_ctime}.
-\item[\const{SHM\_LOCK}] Abilita il \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; si ricordi
-    quanto trattato in \secref{sec:proc_mem_lock}.} sul segmento di memoria
-  condivisa. Solo l'amministratore può utilizzare questo comando.
+\item[\const{SHM\_LOCK}] Abilita il  
+  \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
+  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.
 \end{basedescript}
-i primi tre comandi sono gli stessi già visti anche per le code ed i semafori,
-gli ultimi due sono delle estensioni previste da Linux. 
-
-Per utilizzare i segmenti di memoria condivisa l'interfaccia prevede due
-funzioni, la prima è \funcd{shmat}, che serve ad agganciare un segmento al
-processo chiamante, in modo che quest'ultimo possa vederlo nel suo spazio di
-indirizzi; il suo prototipo è:
+i primi tre comandi sono gli stessi già visti anche per le code di messaggi e
+gli insiemi di semafori, gli ultimi due sono delle estensioni specifiche
+previste da Linux, che permettono di abilitare e disabilitare il meccanismo
+della memoria virtuale\index{memoria virtuale} per il segmento.
+
+L'argomento \param{buf} viene utilizzato solo con i comandi \const{IPC\_STAT}
+e \const{IPC\_SET} nel qual caso esso dovrà puntare ad una struttura
+\struct{shmid\_ds} precedentemente allocata, in cui nel primo caso saranno
+scritti i dati del segmento di memoria restituiti dalla funzione e da cui, nel
+secondo caso, verranno letti i dati da impostare sul segmento.
+
+Una volta che lo si è creato, per utilizzare un segmento di memoria condivisa
+l'interfaccia prevede due funzioni, \funcd{shmat} e \func{shmdt}. La prima di
+queste serve ad agganciare un segmento al processo chiamante, in modo che
+quest'ultimo possa inserirlo nel suo spazio di indirizzi per potervi accedere;
+il suo prototipo è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{sys/shm.h}
@@ -2926,6 +2654,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
+\figref{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
@@ -2940,22 +2717,249 @@ sequenziale\footnote{come accennato in \secref{sec:ipc_sysv_mq} per la
 modalità predefinita.
 
 Un esempio classico di uso della memoria condivisa è quello del
-``\textit{monitor}'', in cui essa viene per scambiare informazioni fra un
-processo server che vi scrive dei dati di interesse generale che ha
-ottenuto, e tutti i processi client interessati agli stessi dati che così
-possono leggerli in maniera completamente asincrona.  Con questo schema di
-funzionamento da una parte si evita che ciascun processo client debba
-compiere l'operazione, potenzialmente onerosa, di ricavare e trattare i dati,
-e dall'altra si evita al processo server di dover gestire l'invio a tutti
-i client di tutti i dati (non potendo il server sapere quali di essi servono
-effettivamente al singolo client).
+``\textit{monitor}'', in cui viene per scambiare informazioni fra un processo
+server, che vi scrive dei dati di interesse generale che ha ottenuto, e i
+processi client interessati agli stessi dati che così possono leggerli in
+maniera completamente asincrona.  Con questo schema di funzionamento da una
+parte si evita che ciascun processo client debba compiere l'operazione,
+potenzialmente onerosa, di ricavare e trattare i dati, e dall'altra si evita
+al processo server di dover gestire l'invio a tutti i client di tutti i dati
+(non potendo il server sapere quali di essi servono effettivamente al singolo
+client).
 
 Nel nostro caso implementeremo un ``\textsl{monitor}'' di una directory: un
 processo si incaricherà di tenere sotto controllo alcuni parametri relativi ad
-una directory (il numero dei file contenuti, la dimensione totale, ecc.) che
-saranno salvati in un segmento di memoria condivisa cui altri processi
-potranno accedere per ricavare la parte di informazione che interessa.
+una directory (il numero dei file contenuti, la dimensione totale, quante
+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
+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
+video; al solito il codice completo si trova con i sorgenti allegati nel file
+\file{DirMonitor.c}.
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/DirMonitor.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice della funzione principale del programma \file{DirMonitor.c}.}
+  \label{fig:ipc_dirmonitor_main}
+\end{figure}
+
+Il programma usa delle variabili globali (\texttt{\small 2--14}) per mantenere
+i valori relativi agli oggetti usati per la comunicazione inter-processo; si è
+definita inoltre una apposita struttura \struct{DirProp} che contiene i dati
+relativi alle proprietà che si vogliono mantenere nella memoria condivisa, per
+l'accesso da parte dei client.
+
+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
+  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 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
+  particolare scopo del programma, che necessita comunque di restare
+  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 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 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 \secref{sec:ipc_sysv_sem}, anche un mutex, che
+utilizzeremo per regolare l'accesso alla memoria condivisa.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/ComputeValues.c}
+  \end{minipage} 
+  \normalsize 
+  \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
+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
+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}.
+
+Dato che la funzione è chiamata da \func{DirScan}, si è all'interno del ciclo
+principale del programma, con un mutex acquisito, perciò non è necessario
+effettuare nessun controllo e si può accedere direttamente alla memoria
+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 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}) 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]{15.6 cm}
+    \includecodesample{listati/ReadMonitor.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice del programma client del monitor delle proprietà di una
+    directory, \file{ReadMonitor.c}.}
+  \label{fig:ipc_dirmonitor_client}
+\end{figure}
+
+Il codice del client usato per 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}.
+
+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}) 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.  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
+il mutex, prima di uscire.
+
+Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando
+le funzioni di libreria occorre definire opportunamente
+\code{LD\_LIBRARY\_PATH}; poi si potrà lanciare il server con:
+\begin{verbatim}
+[piccardi@gont sources]$ ./dirmonitor ./
+\end{verbatim}%$
+ed avendo usato \func{daemon} il comando ritornerà immediatamente. Una volta
+che il server è in esecuzione, possiamo passare ad invocare il client per
+verificarne i risultati, in tal caso otterremo:
+\begin{verbatim}
+[piccardi@gont sources]$ ./readmon 
+Ci sono 68 file dati
+Ci sono 3 directory
+Ci sono 0 link
+Ci sono 0 fifo
+Ci sono 0 socket
+Ci sono 0 device a caratteri
+Ci sono 0 device a blocchi
+Totale  71 file, per 489831 byte
+\end{verbatim}%$
+ed un rapido calcolo (ad esempio con \code{ls -a | wc} per contare i file) ci
+permette di verificare che il totale dei file è giusto. Un controllo con
+\cmd{ipcs} ci permette inoltre di verificare la presenza di un segmento di
+memoria condivisa e di un semaforo:
+\begin{verbatim}
+[piccardi@gont sources]$ ipcs
+------ Shared Memory Segments --------
+key        shmid      owner      perms      bytes      nattch     status      
+0xffffffff 54067205   piccardi  666        4096       1                       
+
+------ Semaphore Arrays --------
+key        semid      owner      perms      nsems     
+0xffffffff 229376     piccardi  666        1         
+
+------ Message Queues --------
+key        msqid      owner      perms      used-bytes   messages    
+\end{verbatim}%$
+
+Se a questo punto aggiungiamo un file, ad esempio con \code{touch prova},
+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
+Ci sono 3 directory
+Ci sono 0 link
+Ci sono 0 fifo
+Ci sono 0 socket
+Ci sono 0 device a caratteri
+Ci sono 0 device a blocchi
+Totale  72 file, per 489887 byte
+\end{verbatim}%$
+
+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 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 --------
+key        shmid      owner      perms      bytes      nattch     status      
+
+------ Semaphore Arrays --------
+key        semid      owner      perms      nsems     
+
+------ Message Queues --------
+key        msqid      owner      perms      used-bytes   messages    
+\end{verbatim}%$
 
 
 
@@ -2981,9 +2985,9 @@ potranno accedere per ricavare la parte di informazione che interessa.
 Come abbiamo detto in \secref{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 sono già stati accennati in precedenza) ed elenca alcune possibili
-tecniche alternative, che vogliamo riprendere in questa sezione.
+  capitolo 14.}  Stevens ne effettua una accurata analisi (alcuni dei concetti
+sono già stati accennati in precedenza) ed elenca alcune possibili tecniche
+alternative, che vogliamo riprendere in questa sezione.
 
 
 \subsection{Alternative alle code di messaggi}
@@ -3005,8 +3009,6 @@ diversa con un uso combinato della memoria condivisa e dei meccanismi di
 sincronizzazione, per cui alla fine l'uso delle code di messaggi classiche è
 relativamente poco diffuso.
 
-
-
 \subsection{I \textsl{file di lock}}
 \label{sec:ipc_file_lock}
 
@@ -3026,12 +3028,13 @@ caratteristica della funzione \func{open} (illustrata in
 \secref{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 condition.} che essa
-ritorni un errore quando usata con i flag di \const{O\_CREAT} e
-\const{O\_EXCL}. In tal modo la creazione di un \textsl{file di lock} può
-essere eseguita atomicamente, il processo che crea il file con successo si può
-considerare come titolare del lock (e della risorsa ad esso associata) mentre
-il rilascio si può eseguire con una chiamata ad \func{unlink}.
+  è comunque soggetti alla possibilità di una race   
+  condition\index{race condition}.} che essa ritorni un errore quando usata
+con i flag di \const{O\_CREAT} e \const{O\_EXCL}. In tal modo la creazione di
+un \textsl{file di lock} può essere eseguita atomicamente, il processo che
+crea il file con successo si può considerare come titolare del lock (e della
+risorsa ad esso associata) mentre il rilascio si può eseguire con una chiamata
+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}
@@ -3044,27 +3047,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
@@ -3086,13 +3070,13 @@ 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
-sincronizzazione: anzitutto anche in questo caso, in caso di terminazione
-imprevista del processo, si lascia allocata la risorsa (il \textsl{file di
-  lock}) e questa deve essere sempre cancellata esplicitamente.  Inoltre il
-controllo della disponibilità può essere eseguito solo con una tecnica di
-\textit{polling}\index{polling}, ed è quindi molto inefficiente.
+sincronizzazione: anzitutto in caso di terminazione imprevista del processo,
+si lascia allocata la risorsa (il \textsl{file di lock}) e questa deve essere
+sempre cancellata esplicitamente.  Inoltre il controllo della disponibilità
+può essere eseguito solo con una tecnica di \textit{polling}\index{polling},
+ed è quindi molto inefficiente.
 
-La tecnica dei file di lock non di meno ha una sua utilità, e può essere usata
+La tecnica dei file di lock ha comunque una sua utilità, e può essere usata
 con successo quando l'esigenza è solo quella di segnalare l'occupazione di una
 risorsa, senza necessità di attendere che questa si liberi; ad esempio la si
 usa spesso per evitare interferenze sull'uso delle porte seriali da parte di
 accedere alla seriale si limita a segnalare che la risorsa non è
 disponibile.\index{file!di lock|)}
 
+
 \subsection{La sincronizzazione con il \textit{file locking}}
 \label{sec:ipc_lock_file}
 
-Dato che i file di lock presentano gli inconvenienti illustrati in precedenza,
-la tecnica alternativa 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 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 write lock metterà automaticamente il processo in
-stato di attesa, senza necessità di ricorrere al
-\textit{polling}\index{polling} per determinare la disponibilità della
-risorsa, e al rilascio della stessa da parte del processo che la occupava si
-otterrà il nuovo lock atomicamente.
+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
+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
+write lock metterà automaticamente il processo in stato di attesa, senza
+necessità di ricorrere al \textit{polling}\index{polling} per determinare la
+disponibilità della risorsa, e al rilascio della stessa da parte del processo
+che la occupava si otterrà il nuovo lock atomicamente.
 
 Questo approccio presenta il notevole vantaggio che alla terminazione di un
 processo tutti i lock acquisiti vengono rilasciati automaticamente (alla
-chiusura dei relativi file) e non ci si deve preoccupare di niente, inoltre
-non consuma risorse permanentemente allocate nel sistema, lo svantaggio è che
-dovendo fare ricorso a delle operazioni sul filesystem esso è in genere
+chiusura dei relativi file) e non ci si deve preoccupare di niente; inoltre
+non consuma risorse permanentemente allocate nel sistema. Lo svantaggio è che,
+dovendo fare ricorso a delle operazioni sul filesystem, esso è in genere
 leggermente più lento.
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{} 
-/*
- * Function LockMutex: lock a file (creating it if not existent).  
- */
-int LockMutex(const char *path_name)
-{
-    int fd, res;
-    struct flock lock;                                /* file lock structure */
-    /* first open the file (creating it if not existent) */
-    if ( (fd = open(path_name, O_EXCL|O_CREAT)) < 0) {    /* first open file */
-        return fd;
-    }
-    /* 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 */
-    if ( (res = fcntl(fd, F_SETLKW, &lock)) < 0 ) {
-        return res;
-    }
-    return 0;
-}
-/*
- * Function UnLockMutex: unlock a file.  
- */
-int UnlockMutex(const char *path_name)
-{
-    int fd, res;
-    struct flock lock;                                /* file lock structure */
-    /* first open the file */
-    if ( (fd = open(path_name, O_RDWR)) < 0) {            /* first open file */
-        return fd;
-    }
-    /* 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 */
-    if ( (res = fcntl(fd, F_SETLK, &lock)) < 0 ) {
-        return res;
-    }
-    return 0;
-}
-    \end{lstlisting}
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/MutexLocking.c}
   \end{minipage} 
   \normalsize 
-  \caption{Il codice delle funzioni che permettono di creare un
-    \textit{mutex} utilizzando il file locking\index{file!locking}.}
+  \caption{Il codice delle funzioni che permettono per la gestione dei 
+    \textit{mutex} con il file locking\index{file!locking}.}
   \label{fig:ipc_flock_mutex}
 \end{figure}
 
-Il codice per implementare un mutex utilizzando il file
-locking\index{file!locking} è riportato in \figref{fig:ipc_flock_mutex}; a
-differenza del precedente caso in cui si sono usati i semafori le funzioni
-questa volta sono sufficienti due funzioni, \func{LockMutex} e
-\func{UnlockMutex}, usate rispettivamente per acquisire e rilasciare il mutex.
-
-La prima funzione (\texttt{\small 1--22}) serve per acquisire il mutex.
-Anzitutto si apre (\texttt{\small 9--11}), creandolo se non esiste, il file
-specificato dall'argomento \param{pathname}. In caso di errore si ritorna
-immediatamente, altrimenti si prosegue impostando (\texttt{\small 12--16}) la
-struttura \var{lock} in modo da poter acquisire un write lock sul file.
-Infine si richiede (\texttt{\small 17--20}) il file lock (restituendo il
-codice di ritorno di \func{fcntl} caso di errore). Se il file è libero il lock
-è acquisito e la funzione ritorna immediatamente; altrimenti \func{fcntl} si
-bloccherà (si noti che la si è chiamata con \func{F\_SETLKW}) fino al rilascio
-del lock.
-
-La seconda funzione (\texttt{\small 23--44}) serve a rilasciare il mutex. Di
-nuovo si apre (\texttt{\small 30--33}) il file specificato dall'argomento
-\param{pathname} (che stavolta deve esistere), ritornando immediatamente in
-caso di errore. Poi si passa ad inizializzare (\texttt{\small 34--38}) la
-struttura \var{lock} per il rilascio del lock, che viene effettuato
-(\texttt{\small 39--42}) subito dopo.
-
- \subsection{Il \textit{memory mapping} anonimo}
+Il codice delle varie funzioni usate per implementare un mutex utilizzando il
+file locking\index{file!locking} è riportato in \figref{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.
+
+La prima funzione (\texttt{\small 1--5}) è \func{CreateMutex}, e serve a
+creare il mutex; la funzione è estremamente semplice, e si limita
+(\texttt{\small 4}) a creare, con una opportuna chiamata ad \func{open}, il
+file che sarà usato per il successivo file locking, assicurandosi che non
+esista già (nel qual caso segnala un errore); poi restituisce il file
+descriptor che sarà usato dalle altre funzioni per acquisire e rilasciare il
+mutex.
+
+La seconda funzione (\texttt{\small 6--10}) è \func{FindMutex}, che, come la
+precedente, è stata definita per mantenere una analogia con la corrispondente
+funzione basata sui semafori. Anch'essa si limita (\texttt{\small 9}) ad
+aprire il file da usare per il file locking, solo che in questo caso le
+opzioni di \func{open} sono tali che il file in questione deve esistere di
+già.
+
+La terza funzione (\texttt{\small 11--22}) è \func{LockMutex} e serve per
+acquisire il mutex. La funzione definisce (\texttt{\small 14}) e inizializza
+(\texttt{\small 16--19}) la struttura \var{lock} da usare per acquisire un
+write lock sul file, che poi (\texttt{\small 21}) viene richiesto con
+\func{fcntl}, restituendo il valore di ritorno di quest'ultima. Se il file è
+libero il lock viene acquisito e la funzione ritorna immediatamente;
+altrimenti \func{fcntl} si bloccherà (si noti che la si è chiamata con
+\func{F\_SETLKW}) fino al rilascio del lock.
+
+La quarta funzione (\texttt{\small 24--34}) è \func{UnlockMutex} e serve a
+rilasciare il mutex. La funzione è analoga alla precedente, solo che in questo
+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
+precedentemente eseguito il lock può sbloccare il mutex.
+
+La quinta funzione (\texttt{\small 36--39}) è \func{RemoveMutex} e serve a
+cancellare il mutex. Anche questa funzione è stata definita per mantenere una
+analogia con le funzioni basate sui semafori, e si limita a cancellare
+(\texttt{\small 38}) il file con una chiamata ad \func{unlink}. Si noti che in
+questo caso la funzione non ha effetto sui mutex già ottenuti con precedenti
+chiamate a \func{FindMutex} o \func{CreateMutex}, che continueranno ad essere
+disponibili fintanto che i relativi file descriptor restano aperti. Pertanto
+per rilasciare un mutex occorrerà prima chiamare \func{UnlockMutex} oppure
+chiudere il file usato per il lock.
+
+La sesta funzione (\texttt{\small 41--55}) è \func{ReadMutex} e serve a
+leggere lo stato del mutex. In questo caso si prepara (\texttt{\small 46--49})
+la solita struttura \var{lock} come l'acquisizione del lock, ma si effettua
+(\texttt{\small 51}) la chiamata a \func{fcntl} usando il comando
+\const{F\_GETLK} per ottenere lo stato del lock, e si restituisce
+(\texttt{\small 52}) il valore di ritorno in caso di errore, ed il valore del
+campo \var{l\_type} (che descrive lo stato del lock) altrimenti
+(\texttt{\small 54}). Per questo motivo la funzione restituirà -1 in caso di
+errore e uno dei due valori \const{F\_UNLCK} o \const{F\_WRLCK}\footnote{non
+  si dovrebbe mai avere il terzo valore possibile, \const{F\_RDLCK}, dato che
+  la nostra interfaccia usa solo i write lock. Però è sempre possibile che
+  siano richiesti altri lock sul file al di fuori dell'interfaccia, nel qual
+  caso si potranno avere, ovviamente, interferenze indesiderate.} in caso di
+successo, ad indicare che il mutex è, rispettivamente, libero o occupato.
+
+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
+\func{UnlockMutex} o \func{LockMutex} non si cumulano e non danno perciò
+nessun inconveniente.
+
+
+\subsection{Il \textit{memory mapping} anonimo}
 \label{sec:ipc_mmap_anonymous}
 
 Abbiamo già visto che quando i processi sono \textsl{correlati}\footnote{se
@@ -3211,7 +3198,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.
 
-Abbiamo visto in \secref{sec:file_memory_map} che è possibile mappare il
+In \secref{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
@@ -3230,8 +3217,9 @@ il \textit{memory mapping} anonimo.\footnote{nei sistemi derivati da SysV una
   \file{/dev/zero}. In tal caso i valori scritti nella regione mappata non
   vengono ignorati (come accade qualora si scriva direttamente sul file), ma
   restano in memoria e possono essere riletti secondo le stesse modalità usate
-  nel \textit{memory mapping} anonimo.} Un esempio di utilizzo di questa
-tecnica è mostrato in 
+  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.
 
 
 
@@ -3245,29 +3233,506 @@ meccanismi di comunicazione, che vanno sotto il nome di POSIX IPC, definendo
 una interfaccia completamente nuova, che tratteremo in questa sezione.
 
 
-
 \subsection{Considerazioni generali}
 \label{sec:ipc_posix_generic}
 
-Il Linux non tutti gli oggetti del POSIX IPC sono supportati nel kernel
-ufficiale; solo la memoria condivisa è presente, ma solo a partire dal kernel
-2.4.x, per gli altri oggetti esistono patch e librerie non ufficiali.
-Nonostante questo è importante esaminare questa interfaccia per la sua netta
-superiorità nei confronti di quella del \textit{SysV IPC}.
+In Linux non tutti gli oggetti del POSIX IPC sono pienamente supportati nel
+kernel ufficiale; solo la memoria condivisa è presente con l'interfaccia
+completa, ma solo a partire dal kernel 2.4.x, i semafori sono forniti dalle
+\acr{glibc} nella sezione che implementa i thread POSIX, le code di messaggi
+non hanno alcun tipo di supporto ufficiale.  Per queste ultime esistono
+tuttavia dei patch e una libreria aggiuntiva.
+
+La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso
+degli identificatori e delle chiavi visti nel SysV IPC, per passare ai
+\textit{Posix IPC names}\index{Posix IPC names}, che sono sostanzialmente
+equivalenti ai nomi dei file. Tutte le funzioni che creano un oggetto di IPC
+Posix prendono come primo argomento una stringa che indica uno di questi nomi;
+lo standard è molto generico riguardo l'implementazione, ed i nomi stessi
+possono avere o meno una corrispondenza sul filesystem; tutto quello che è
+richiesto è che:
+\begin{itemize}
+\item i nomi devono essere conformi alle regole che caratterizzano i
+  \textit{pathname}, in particolare non essere più lunghi di \const{PATH\_MAX}
+  byte e terminati da un carattere nullo.
+\item se il nome inizia per una \texttt{/} chiamate differenti allo stesso
+  nome fanno riferimento allo stesso oggetto, altrimenti l'interpretazione del
+  nome dipende dall'implementazione.
+\item l'interpretazione di ulteriori \texttt{/} presenti nel nome dipende
+  dall'implementazione.
+\end{itemize}
+
+Data la assoluta genericità delle specifiche, il comportamento delle funzioni
+è 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, 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 \secref{sec:ipc_posix_shm} e \secref{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 è 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
+quella particolare (si ricordi quanto visto in
+\secref{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
+processo che esegue la creazione).
+
 
 
 \subsection{Code di messaggi}
 \label{sec:ipc_posix_mq}
 
-Le code di messaggi non sono ancora supportate nel kernel
-ufficiale;\footnote{esiste però una proposta di implementazione di Krzysztof
-  Benedyczak, a partire dal kernel 2.5.50.}  inoltre esse possono essere
-implementate, usando la memoria condivisa ed i mutex, con funzioni di
-libreria. In generale, come le corrispettive del SysV IPC, sono poco usate,
-dato che i socket\index{socket}, nei casi in cui sono sufficienti, sono più
-comodi, e negli altri casi la comunicazione può essere gestita direttamente
-con mutex e memoria condivisa. Per questo ci limiteremo ad una descrizione
-essenziale.
+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 su
+\href{http://www.mat.uni.torun.pl/~wrona/posix_ipc}
+{http://www.mat.uni.torun.pl/\tild{}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.
+
+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.}
+
+
+La libreria inoltre richiede la presenza dell'apposito filesystem di tipo
+\texttt{mqueue} montato su \file{/dev/mqueue}; questo può essere fatto
+aggiungendo ad \file{/etc/fstab} una riga come:
+\begin{verbatim}
+mqueue   /dev/mqueue       mqueue    defaults        0      0
+\end{verbatim}
+ed esso sarà utilizzato come radice sulla quale vengono risolti i nomi delle
+code di messaggi che iniziano con una \texttt{/}. Le opzioni di mount
+accettate sono \texttt{uid}, \texttt{gid} e \texttt{mode} che permettono
+rispettivamente di impostare l'utente, il gruppo ed i permessi associati al
+filesystem.
+
+
+La funzione che permette di aprire (e crearla se non esiste ancora) una coda
+di messaggi POSIX è \funcd{mq\_open}, ed il suo prototipo è:
+\begin{functions}
+  \headdecl{mqueue.h} 
+  
+  \funcdecl{mqd\_t mq\_open(const char *name, int oflag)}
+  
+  \funcdecl{mqd\_t mq\_open(const char *name, int oflag, unsigned long mode,
+    struct mq\_attr *attr)}
+  
+  Apre una coda di messaggi POSIX impostandone le caratteristiche.
+  
+  \bodydesc{La funzione restituisce il descrittore associato alla coda in caso
+    di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i
+    valori:
+    \begin{errlist}
+    \item[\errcode{EACCESS}] Il processo non ha i privilegi per accedere al
+      alla memoria secondo quanto specificato da \param{oflag}.
+    \item[\errcode{EEXIST}] Si è specificato \const{O\_CREAT} e
+      \const{O\_EXCL} ma la coda già esiste.
+    \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+    \item[\errcode{EINVAL}] Il file non supporta la funzione, o si è
+      specificato \const{O\_CREAT} con una valore non nullo di \param{attr} e
+      valori non validi di \var{mq\_maxmsg} e \var{mq\_msgsize}.
+    \item[\errcode{ENOENT}] Non si è specificato \const{O\_CREAT} ma la coda
+      non esiste.
+    \end{errlist}
+    ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT},
+    \errval{EMFILE} ed \errval{ENFILE}.}
+\end{functions}
+
+La funzione apre la coda di messaggi identificata dall'argomento \param{name}
+restituendo il descrittore ad essa associato, del tutto analogo ad un file
+descriptor, con l'unica differenza che lo standard prevede un apposito tipo
+\type{mqd\_t}.\footnote{nella implementazione citata questo è definito come
+  \ctyp{int}.} Se la coda esiste già il descrittore farà riferimento allo
+stesso oggetto, consentendo così la comunicazione fra due processi diversi.
+
+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
+seguenti:
+\begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{O\_RDONLY}] Apre la coda solo per la ricezione di messaggi. Il
+  processo potrà usare il descrittore con \func{mq\_receive} ma non con
+  \func{mq\_send}.
+\item[\const{O\_WRONLY}] Apre la coda solo per la trasmissione di messaggi. Il
+  processo potrà usare il descrittore con \func{mq\_send} ma non con
+  \func{mq\_receive}.
+\item[\const{O\_RDWR}] Apre la coda solo sia per la trasmissione che per la
+  ricezione. 
+\item[\const{O\_CREAT}] Necessario qualora si debba creare la coda; la
+  presenza di questo bit richiede la presenza degli ulteriori argomenti
+  \param{mode} e \param{attr}.
+\item[\const{O\_EXCL}] Se usato insieme a \const{O\_CREAT} fa fallire la
+  chiamata se la coda esiste già, altrimenti esegue la creazione atomicamente.
+\item[\const{O\_NONBLOCK}] Imposta la coda in modalità non bloccante, le
+  funzioni di ricezione e trasmissione non si bloccano quando non ci sono le
+  risorse richieste, ma ritornano immediatamente con un errore di
+  \errcode{EAGAIN}.
+\end{basedescript}
+
+I primi tre bit specificano la modalità di apertura della coda, e sono fra
+loro esclusivi. Ma qualunque sia la modalità in cui si è aperta una coda,
+questa potrà essere riaperta più volte in una modalità diversa, e vi si potrà
+sempre accedere attraverso descrittori diversi, esattamente come si può fare
+per i file normali.
+
+Se la coda non esiste e la si vuole creare si deve specificare
+\const{O\_CREAT}, in tal caso occorre anche specificare i permessi di
+creazione con l'argomento \param{mode}; i valori di quest'ultimo sono identici
+a quelli usati per \func{open}, anche se per le code di messaggi han senso
+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}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/mq_attr.h}
+  \end{minipage} 
+  \normalsize
+  \caption{La struttura \structd{mq\_attr}, contenente gli attributi di una
+    coda di messaggi POSIX.}
+  \label{fig:ipc_mq_attr}
+\end{figure}
+
+Per ls creazione della coda i campi della struttura che devono essere
+specificati sono \var{mq\_msgsize} e \var{mq\_maxmsg}, che indicano
+rispettivamente la dimensione massima di un messaggio ed il numero massimo di
+messaggi che essa può contenere. Il valore dovrà essere positivo e minore dei
+rispettivi limiti di sistema \const{MQ\_MAXMSG} e \const{MQ\_MSGSIZE},
+altrimenti la funzione fallirà con un errore di \errcode{EINVAL}.  Qualora si
+specifichi per \param{attr} un puntatore nullo gli attributi della coda
+saranno impostati ai valori predefiniti.
+
+Quando l'accesso alla coda non è più necessario si può chiudere il relativo
+descrittore con la funzione \funcd{mq\_close}, il cui prototipo è:
+\begin{prototype}{mqueue.h}
+{int mq\_close(mqd\_t mqdes)}
+
+Chiude 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 \errval{EBADF} o
+  \errval{EINTR}.}
+\end{prototype}
+
+La funzione è analoga a \func{close},\footnote{in Linux, dove le code sono
+  implementate come file su un filesystem dedicato, è esattamente la stessa
+  funzione.} dopo la sua esecuzione il processo non sarà più in grado di usare
+il descrittore della coda, ma quest'ultima continuerà ad esistere nel sistema
+e potrà essere acceduta con un'altra chiamata a \func{mq\_open}. All'uscita di
+un processo tutte le code aperte, così come i file, vengono chiuse
+automaticamente. Inoltre se il processo aveva agganciato una richiesta di
+notifica sul descrittore che viene chiuso, questa sarà rilasciata e potrà
+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)}
+
+Rimuove una coda di messaggi.
+  
+\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}
+
+Anche in questo caso il comportamento della funzione è analogo a quello di
+\func{unlink} per i file,\footnote{di nuovo l'implementazione di Linux usa
+  direttamente \func{unlink}.} la funzione rimove la coda \param{name}, così
+che una successiva chiamata a \func{mq\_open} fallisce o crea una coda
+diversa. 
+
+Come per i file ogni coda di messaggi ha un contatore di riferimenti, per cui
+la coda non viene effettivamente rimossa dal sistema fin quando questo non si
+annulla. Pertanto anche dopo aver eseguito con successo \func{mq\_unlink} la
+coda resterà accessibile a tutti i processi che hanno un descrittore aperto su
+di essa.  Allo stesso modo una coda ed i suoi contenuti resteranno disponibili
+all'interno del sistema anche quando quest'ultima non è aperta da nessun
+processo (questa è una delle differenze più rilevanti nei confronti di pipe e
+fifo).
+
+La sola differenza fra code di messaggi POSIX e file normali è che, essendo il
+filesystem delle code di messaggi virtuale e basato su oggetti interni al
+kernel, il suo contenuto viene perduto con il riavvio del sistema.
+
+Come accennato in precedenza ad ogni coda di messaggi è associata una
+struttura \struct{mq\_attr}, che può essere letta e modificata attraverso le
+due funzioni \funcd{mq\_getattr} e \funcd{mq\_setattr}, i cui prototipi sono:
+\begin{functions}
+  \headdecl{mqueue.h} 
+  
+  \funcdecl{int mq\_getattr(mqd\_t mqdes, struct mq\_attr *mqstat)}
+  Legge gli attributi di una coda di messaggi POSIX.
+  
+  \funcdecl{int mq\_setattr(mqd\_t mqdes, const struct mq\_attr *mqstat,
+    struct mq\_attr *omqstat)}
+  Modifica gli attributi di una coda di messaggi POSIX.
+  
+  \bodydesc{Entrambe le funzioni restituiscono 0 in caso di successo e -1 in
+    caso di errore; nel quel caso \var{errno} assumerà i valori \errval{EBADF}
+    o \errval{EINVAL}.}
+\end{functions}
+
+La funzione \func{mq\_getattr} legge i valori correnti degli attributi della
+coda nella struttura puntata da \param{mqstat}; di questi l'unico relativo
+allo stato corrente della coda è \var{mq\_curmsgs} che indica il numero di
+messaggi da essa contenuti, gli altri indicano le caratteristiche generali
+della stessa.
+
+La funzione \func{mq\_setattr} permette di modificare gli attributi di una
+coda tramite i valori contenuti nella struttura puntata da \param{mqstat}, ma
+può essere modificato solo il campo \var{mq\_flags}, gli altri campi vengono
+ignorati. In particolare i valori di \var{mq\_maxmsg} e \var{mq\_msgsize}
+possono essere specificati solo in fase ci creazione della coda.  Inoltre i
+soli valori possibili per \var{mq\_flags} sono 0 e \const{O\_NONBLOCK}, per
+cui alla fine la funzione può essere utilizzata solo per abilitare o
+disabilitare la modalità non bloccante. L'argomento \param{omqstat} viene
+usato, quando diverso da \val{NULL}, per specificare l'indirizzo di una
+struttura su cui salvare i valori degli attributi precedenti alla chiamata
+della funzione.
+
+Per inserire messaggi su di una coda sono previste due funzioni,
+\funcd{mq\_send} e \funcd{mq\_timedsend}, i cui prototipi sono:
+\begin{functions}
+  \headdecl{mqueue.h} 
+  
+  \funcdecl{int mq\_send(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len,
+    unsigned int msg\_prio)} 
+  Esegue l'inserimento di un messaggio su una coda.
+  
+  \funcdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t
+    msg\_len, unsigned msg\_prio, const struct timespec *abs\_timeout)}   
+  Esegue l'inserimento di un messaggio su una coda entro il tempo
+  \param{abs\_timeout}.
+
+  
+  \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+    errore; nel quel caso \var{errno} assumerà i valori:
+    \begin{errlist}
+    \item[\errcode{EAGAIN}] Si è aperta la coda con \const{O\_NONBLOCK}, e la
+      coda è piena.
+    \item[\errcode{EMSGSIZE}] La lunghezza del messaggio \param{msg\_len}
+      eccede il limite impostato per la coda.
+    \item[\errcode{ENOMEM}] Il kernel non ha memoria sufficiente. Questo
+      errore può avvenire quando l'inserimento del messaggio
+    \item[\errcode{EINVAL}] Si è specificato un valore nullo per
+      \param{msg\_len}, o un valore di \param{msg\_prio} fuori dai limiti, o
+      un valore non valido per \param{abs\_timeout}.
+    \item[\errcode{ETIMEDOUT}] L'inserimento del messaggio non è stato
+      effettuato entro il tempo stabilito.
+    \end{errlist}    
+    ed inoltre \errval{EBADF} ed \errval{EINTR}.}
+\end{functions}
+
+Entrambe le funzioni richiedono un puntatore al testo del messaggio
+nell'argomento \param{msg\_ptr} e la relativa lunghezza in \param{msg\_len}.
+Se quest'ultima eccede la dimensione massima specificata da \var{mq\_msgsize}
+le funzioni ritornano immediatamente con un errore di \errcode{EMSGSIZE}.
+
+L'argomento \param{msg\_prio} indica la priorità dell'argomento; i messaggi di
+priorità maggiore vengono inseriti davanti a quelli di priorità inferiore (e
+quindi saranno riletti per primi). A parità del valore della priorità il
+messaggio sarà inserito in coda a tutti quelli con la stessa priorità. Il
+valore della priorità non può eccedere il limite di sistema
+\const{MQ\_PRIO\_MAX}, che nel caso è pari a 32768.
+
+Qualora la coda sia piena, entrambe le funzioni si bloccano, a meno che non
+sia stata selezionata in fase di apertura la modalità non bloccante, nel qual
+caso entrambe ritornano \errcode{EAGAIN}. La sola differenza fra le due
+funzioni è che la seconda, passato il tempo massimo impostato con l'argomento
+\param{abs\_timeout}, ritorna comunque con un errore di \errcode{ETIMEDOUT}.
+
+
+Come per l'inserimento, anche per l'estrazione dei messaggi da una coda sono
+previste due funzioni, \funcd{mq\_receive} e \funcd{mq\_timedreceive}, i cui
+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\_timedreceive(mqd\_t mqdes, char *msg\_ptr, size\_t
+    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}.
+  
+  \bodydesc{Le funzioni restituiscono il numero di byte del messaggio in caso
+    di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i
+    valori:
+    \begin{errlist}
+    \item[\errcode{EAGAIN}] Si è aperta la coda con \const{O\_NONBLOCK}, e la
+      coda è vuota.
+    \item[\errcode{EMSGSIZE}] La lunghezza del messaggio sulla coda eccede il
+      valore \param{msg\_len} specificato per la ricezione.
+    \item[\errcode{EINVAL}] Si è specificato un valore nullo per
+      \param{msg\_ptr}, o un valore non valido per \param{abs\_timeout}.
+    \item[\errcode{ETIMEDOUT}] La ricezione del messaggio non è stata
+      effettuata entro il tempo stabilito.
+    \end{errlist}    
+    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
+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, 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
+immediatamente con l'errore \errcode{EAGAIN}. Anche in questo caso la sola
+differenza fra le due funzioni è che la seconda non attende indefinitamente e
+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 \figref{fig:file_sigevent}) introdotta dallo
+standard POSIX.1b per gestire la notifica di eventi; per altri dettagli si può
+vedere quanto detto in \secref{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
+\figref{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 \secref{sec:sig_real_time} a proposito dei segnali
+  real-time.} posto che questo sia installato nella forma estesa vista in
+\secref{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
+\figref{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 \secref{sec:sig_sigaction} e \secref{sec:sig_real_time}.}
 
 
 
@@ -3276,16 +3741,203 @@ essenziale.
 
 Dei semafori POSIX esistono sostanzialmente due implementazioni; una è fatta a
 livello di libreria ed è fornita dalla libreria dei thread; questa però li
-implementa solo a livello di thread e non di processi. Esiste un'altra
-versione, realizzata da Konstantin Knizhnik, che reimplementa l'interfaccia
-POSIX usando i semafori di SysV IPC. 
+implementa solo a livello di thread e non di processi.\footnote{questo
+  significa che i semafori sono visibili solo all'interno dei thread creati da
+  un singolo processo, e non possono essere usati come meccanismo di
+  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
+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.
+
+
 
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_posix_shm}
 
 La memoria condivisa è l'unico degli oggetti di IPC POSIX già presente nel
-kernel ufficiale. 
+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}. 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=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 \secref{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
+\tabref{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 \secref{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
+\secref{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
+\secref{fig:ipc_sysv_shm_func} per la memoria condivisa in stile SysV. Il
+codice, riportato in \figref{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.
+
 
 
 %%% Local Variables: