Ancora message queues
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 2e4d3811119702c993539b5554b91e0f29e638e9..029284fb19b426022a8a2c6e5ae18b5c72e971cf 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -349,7 +349,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 è:
@@ -600,7 +600,7 @@ int main(int argc, char *argv[])
 {
 /* Variables definition */
     int i, n = 0;
-    char *fortunefilename = "/usr/share/games/fortunes/italia";
+    char *fortunefilename = "/usr/share/games/fortunes/linux";
     char **fortune;
     char line[80];
     int fifo_server, fifo_client;
@@ -617,6 +617,7 @@ int main(int argc, char *argv[])
             exit(1);
         }
     }
+    daemon(0, 0);
     /* open fifo two times to avoid EOF */
     fifo_server = open(fifoname, O_RDONLY);
     if (fifo_server < 0) {
@@ -676,41 +677,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 +724,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
@@ -802,6 +807,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
@@ -1631,7 +1692,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 +1701,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ù
@@ -1702,7 +1763,7 @@ int main(int argc, char *argv[])
 /* Variables definition */
     int i, n = 0;
     char **fortune;                       /* array of fortune message string */
-    char *fortunefilename;                              /* fortune file name */
+    char *fortunefilename = "/usr/share/games/fortunes/linux";  /* file name */
     struct msgbuf_read {      /* message struct to read request from clients */
         long mtype;                               /* message type, must be 1 */
         long pid;             /* message data, must be the pid of the client */
@@ -1727,6 +1788,7 @@ int main(int argc, char *argv[])
         exit(1);
     }
     /* Main body: loop over requests */
+    daemon(0, 0);
     while (1) {
         msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR);
         n = random() % i;                             /* select random value */
@@ -1774,7 +1836,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,33 +1846,35 @@ 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
@@ -1868,6 +1932,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
@@ -2569,25 +2670,26 @@ 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
-smemaforo; il valore di ritorno di quest'ultima viene passato all'indietro.
+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.
+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}
 \label{sec:ipc_sysv_shm}
 
@@ -2694,7 +2796,9 @@ 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. 
@@ -2751,49 +2855,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}
@@ -2967,9 +3086,6 @@ video; al solito il codice completo si trova con i sorgenti allegati nel file
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{} 
-/* computation function for DirScan */
-int ComputeValues(struct dirent * direntry);
-void HandSIGTERM(int signo);
 /* global variables for shared memory segment */
 struct DirProp {
     int tot_size;    
@@ -2981,8 +3097,7 @@ struct DirProp {
     int tot_block;   
     int tot_char;    
     int tot_sock;
-};
-struct DirProp *shmptr;
+} *shmptr;
 int shmid; 
 int mutex;
 /* main body */
@@ -2995,11 +3110,13 @@ int main(int argc, char *argv[])
         printf("Wrong number of arguments %d\n", argc - optind);
         usage();
     }
+    if (chdir(argv[1])) {                      /* chdir to be sure dir exist */
+        perror("Cannot find directory to monitor");
+    }
     Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
     Signal(SIGINT, HandSIGTERM);
     Signal(SIGQUIT, HandSIGTERM);
-    /* create needed IPC objects */
-    key = ftok("./DirMonitor.c", 1);                         /* define a key */
+    key = ftok("~/gapil/sources/DirMonitor.c", 1);           /* define a key */
     shmid = shmget(key, 4096, IPC_CREAT|0666);        /* get a shared memory */
     if (shmid < 0) {
         perror("Cannot create shared memory");
@@ -3007,12 +3124,14 @@ int main(int argc, char *argv[])
     }
     if ( (shmptr = shmat(shmid, NULL, 0)) == NULL ) {   /* attach to process */
         perror("Cannot attach segment");
+        exit(1);
     }
     if ((mutex = MutexCreate(key)) == -1) {                   /* get a Mutex */
         perror("Cannot create mutex");
         exit(1);
     }
     /* main loop, monitor directory properties each 10 sec */
+    daemon(1, 0);              /* demonize process, staying in monitored dir */
     while (1) {
         MutexLock(mutex);                              /* lock shared memory */
         memset(shmptr, 0, sizeof(struct DirProp));    /* erase previous data */
@@ -3028,54 +3147,78 @@ int main(int argc, char *argv[])
   \label{fig:ipc_dirmonitor_main}
 \end{figure}
 
-Il programma usa delle variabili globali (\texttt{\small 4--18}) per mantenere
+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 comandoche si limitano alla eventuale stampa di un messaggio di
+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
-  25--28}) che sia stato specificato un parametro (il nome della directory da
-tenere sotto controllo) senza il quale esce immediatamente con un messaggio di
-errore.
-
-Il passo successivo (\texttt{\small 29--31}) è quello di installare i gestori
-per i segnali di terminazione, infatti, visto che il programma è progettato
-come server, non è prevista una conclusione esplicita nel corpo principale,
-per cui, per gestire l'uscita, si è fatto uso di questi ultimi.
-
-Si può poi passare a creare (\texttt{\small 32--45}) gli oggetti di
-intercomunicazione necessari. Si ricava (\texttt{\small 33}) una chiave usando
-il nome del programma, con questa si ottiene (\texttt{\small 34--38}) un
-segmento di memoria condivisa \var{shmid} (uscendo in caso di errore), che si
-aggancia (\texttt{\small 39--41}) al processo all'indirizzo \var{shmptr}; sarà
-attraverso questo puntatore che potremo accedere alla memoria condivisa, che
-sarà vista nella forma data da \struct{DirProp}. Infine con la stessa chiave
-si crea (\texttt{\small 42--45}) anche un mutex (utilizzando le funzioni di
-interfaccia già descritte in \secref{sec:ipc_sysv_sem}) che utilizzeremo per
-regolare l'accesso alla memoria condivisa.
+ripetuto il calcolo delle proprietà della directory) controlla (\texttt{\small
+  21--24}) che sia stato specificato il parametro necessario contenente il
+nome della directory da tenere sotto controllo, senza il quale esce
+immediatamente con un messaggio di errore.
+
+Poi, per verificare che il parametro specifichi effettivamente una directory,
+si esegue (\texttt{\small 25--27}) su di esso una \func{chdir}, uscendo
+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 28--30}) si installano
+i gestori per i vari segnali di terminazione che, avendo a che fare con un
+programma che deve essere eseguito come server, sono il solo strumento
+disponibile per concluderne l'esecuzione.
+
+Il passo successivo (\texttt{\small 31--44}) è quello di creare gli oggetti di
+intercomunicazione necessari. Si inizia costruendo (\texttt{\small 31}) la
+chiave da usare come riferimento con il nome del programma,\footnote{si è
+  usato un riferimento relativo alla home dell'utente, supposto che i sorgenti
+  di GaPiL siano stati installati direttamente in essa. Qualora si effettui
+  una installazione diversa si dovrà correggere il programma.} dopo di che si
+richiede (\texttt{\small 32}) la creazione di un segmento di memoria condivisa
+con \func{shmget} (una pagina di memoria è sufficiente per i dati che
+useremo), uscendo (\texttt{\small 33--36}) qualora la creazione non abbia
+successo.
+
+Una volta ottenutone l'identificatore in \var{shmid}, si può agganciare
+(\texttt{\small 37--40}) il segmento al processo con \func{shmat} anche in
+questo caso si esce qualora la funzione non abbia successo. Con l'indirizzo
+\var{shmptr} così ottenuto potremo poi accedere alla memoria condivisa, che,
+per come abbiamo lo abbiamo definito, sarà vista nella forma data da
+\struct{DirProp}. Infine (\texttt{\small 41--44}) utilizzando sempre la stessa
+chiave, si crea, tramite le funzioni di interfaccia già descritte in
+\secref{sec:ipc_sysv_sem}, anche un mutex, che utilizzeremo per regolare
+l'accesso alla memoria condivisa.
 
 Una volta completata l'inizializzazione e la creazione degli oggetti di
-intercomunicazione il programma eseguirà indefinitamente (\texttt{\small
-  46--53}) il ciclo principale: si inizia bloccando il mutex (\texttt{\small
-  48}) per poter accedere alla memoria condivisa (la funzione si bloccherà
-automaticamente se qualche client sta leggendo), poi si cancellano
-(\texttt{\small 49}) i valori precedentemente memorizzati, e si esegue
-(\texttt{\small 50}) un nuovo calcolo degli stessi; infine si sblocca il mutex
-(\texttt{\small 51}), e si attende (\texttt{\small 52}) per il periodo di
-tempo specificato a riga di comando con l'opzione \code{-p}.
+intercomunicazione il programma entra nel ciclo principale (\texttt{\small
+  45--54}) dove vengono eseguite indefinitamente le attività di monitoraggio.
+Il primo passo (\texttt{\small 46}) è eseguire \func{daemon} per proseguire con
+l'esecuzione in background come si conviene ad un programma demone; si noti
+che si è mantenuta, usando un valore non nullo del primo argomento, la
+directory di lavoro corrente.
+
+Una volta che il programma è andato in background l'esecuzione prosegue
+(\texttt{\small 47--53}) all'interno di un ciclo infinito: si inizia
+(\texttt{\small 48}) bloccando il mutex con \func{MutexLock} per poter
+accedere alla memoria condivisa (la funzione si bloccherà automaticamente se
+qualche client sta leggendo), poi (\texttt{\small 49}) si cancellano i valori
+precedentemente immagazzinati nella memoria condivisa con \func{memset}, e si
+esegue (\texttt{\small 50}) un nuovo calcolo degli stessi utilizzando la
+funzione \func{DirScan}; infine (\texttt{\small 51}) si sblocca il mutex con
+\func{MutexUnlock}, e si attende (\texttt{\small 52}) per il periodo di tempo
+specificato a riga di comando con l'opzione \code{-p} con una \func{sleep}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{} 
-...
-/*
- * Routine  to compute directory properties inside DirScan
- */
+/* Routine  to compute directory properties inside DirScan */
 int ComputeValues(struct dirent * direntry) 
 {
     struct stat data;
@@ -3091,9 +3234,7 @@ int ComputeValues(struct dirent * direntry)
     if (S_ISSOCK(data.st_mode)) shmptr->tot_sock++;
     return 0;
 }
-/*
- * Signal Handler to manage termination
- */
+/* Signal Handler to manage termination */
 void HandSIGTERM(int signo) {
     MutexLock(mutex);
     if (shmdt(shmptr)) {
@@ -3121,56 +3262,43 @@ 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 5--19}) è molto semplice e si limita a
-chiamare (\texttt{\small 8}) la funzione \func{stat} sul file indicato da
+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.
+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} riempiendo i campi della struttura
-\struct{DirProp}; così prima (\texttt{\small 9--10}) si sommano le dimensioni
-dei file ed il loro numero, poi utilizzando le macro di
-\tabref{tab:file_type_macro}, si contano (\texttt{\small 11--17}) quanti ce ne
+condivisa usando \var{shmptr} per riempire i campi della struttura
+\struct{DirProp}; così prima (\texttt{\small 6--7}) si sommano le dimensioni
+dei file ed il loro numero, poi, utilizzando le macro di
+\tabref{tab:file_type_macro}, si contano (\texttt{\small 8--14}) quanti ce ne
 sono per ciascun tipo.
 
-In \figref{fig:ipc_dirmonitor_sub} è riportato anche (\texttt{\small 23--35})
-il codice del gestore di segnali di terminazione usato per chiudere il
-programma, che oltre a provocare l'uscita del programma si incarica anche di
-cancellare tutti gli oggetti di intercomunicazione non più necessari.  Nel
-caso anzitutto (\texttt{\small 24}) si acquisisce il mutex per evitare di
-operare mentre un client sta ancora leggendo i dati, dopo di che prima si
-distacca (\texttt{\small 25--28}) il segmento e poi lo si cancella
-(\texttt{\small 29--32}). Infine (\texttt{\small 33}) si rimuove il mutex e si
-esce.
-
-Il codice del client che permette di leggere le informazioni mantenute nella
-memoria condivisa è riportato in \figref{fig:ipc_dirmonitor_client}, al solito
-si è omessa la sezione di gestione delle opzioni e la funzione che stampa a
-video le istruzioni; il codice completo è nei sorgenti allegati, nel file
-\file{ReadMonitor.c}.
+In \figref{fig:ipc_dirmonitor_sub} è riportato anche (\texttt{\small 17--30})
+il codice del gestore dei segnali di terminazione, usato per chiudere il
+programma. Esso, oltre a provocare l'uscita del programma, si incarica anche
+di cancellare tutti gli oggetti di intercomunicazione non più necessari.  Per
+questo anzitutto (\texttt{\small 19}) acquisisce il mutex con
+\func{MutexLock}, per evitare di operare mentre un client sta ancora leggendo
+i dati, dopo di che (\texttt{\small 20--23}) prima distacca il segmento di
+memoria condivisa con \func{shmad} e poi (\texttt{\small 24--27}) lo cancella
+con \func{shctl}.  Infine (\texttt{\small 28}) rimuove il mutex con
+\func{MutexRemove} ed esce.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{} 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>        /* directory */
-#include <stdlib.h>        /* C standard library */
-#include <unistd.h>
-
-#include "Gapil.h"
-#include "macros.h"
-
 int main(int argc, char *argv[]) 
 {
     int i;
     key_t key;
-    ..
-    /* find needed IPC objects */
-    key = ftok("./DirMonitor.c", 1);                         /* define a key */
+    ...
+    /* create needed IPC objects */
+    key = ftok("~/gapil/sources/DirMonitor.c", 1);           /* define a key */
     shmid = shmget(key, 4096, 0);                /* get the shared memory ID */
     if (shmid < 0) {
         perror("Cannot find shared memory");
@@ -3200,28 +3328,110 @@ int main(int argc, char *argv[])
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{Codice del programma client \file{ReadMonitor.c}.}
+  \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, che permette di leggere le informazioni mantenute nella
+memoria condivisa, è riportato in \figref{fig:ipc_dirmonitor_client}. Al
+solito si è omessa la sezione di gestione delle opzioni e la funzione che
+stampa a video le istruzioni; il codice completo è nei sorgenti allegati, nel
+file \file{ReadMonitor.c}.
+
 Una volta completata la gestione delle opzioni a riga di comando il programma
-rigenera (\texttt{\small 16}) la chiave usata per identificare memoria
-condivisa e mutex, richiede (\texttt{\small 17}) l'identificatore della
-memoria condivisa (che in questo caso deve già esistere), uscendo in caso di
-errore (\texttt{\small 18--21}). Una volta ottenuto l'identificatore si può
-(\texttt{\small 22--25}) agganciare il segmento al processo (anche in questo
-caso uscendo se qualcosa non funziona). Infine (\texttt{\small 26--29}) si
-richiede pure l'identificatore del mutex.
+rigenera (\texttt{\small 7}) con \func{ftok} la stessa chiave usata dal server
+per identificare il segmento di memoria condivisa ed il mutex, poi
+(\texttt{\small 8}) si richiede con \func{semget} l'identificatore della
+memoria condivisa, ma in questo caso si vuole che esso esista di già; al
+solito (\texttt{\small 9--12}) si esce in caso di errore. Una volta ottenuto
+l'identificatore in \var{shmid} si può (\texttt{\small 13--16}) agganciare il
+segmento al processo all'indirizzo \func{shmptr}; anche in questo caso si
+chiude immediatamente il programma se qualcosa non funziona.  Infine
+(\texttt{\small 17--20}) con \func{MutexFind} si richiede l'identificatore del
+mutex.
 
 Una volta completata l'inizializzazione ed ottenuti i riferimenti agli oggetti
 di intercomunicazione necessari viene eseguito il corpo principale del
-programma (\texttt{\small 30--41}); si acquisisce (\texttt{\small 31}) il
-mutex (qui avviene il blocco se la memoria condivisa non è disponibile), e poi
-(\texttt{\small 32--40}) si stampano i vari valori in essa contenuti. Infine
-(\texttt{\small 41}) si rilascia il mutex. 
+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                       
 
-Verifichiamo allora il funzionamento del nostro programma
+------ 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 (passati nel peggiore dei casi almeno 10 secondi, cioè
+l'intervallo scelto per la rilettura dei dati), che:
+\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}%$
+
+Infine potremo terminare il server con il comando \code{killall dirmonitor},
+nel qual caso, ripetendo la lettura otterremo che:
+\begin{verbatim}
+[piccardi@gont sources]$ ./readmon 
+Cannot find shared memory: No such file or directory
+\end{verbatim}%$
+e potremo verificare che anche gli oggetti di intercomunicazione sono stati
+cancellati:
+\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}%$
 
 
 
@@ -3405,7 +3615,6 @@ int FindMutex(const char *path_name)
 int LockMutex(int fd)
 {
     struct flock lock;                                /* file lock structure */
-    /* first open the file (creating it if not existent) */
     /* 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 */
@@ -3476,55 +3685,54 @@ 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--23}) è \func{LockMutex} e serve per
+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 17--20}) la struttura \var{lock} da usare per acquisire un
+(\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--35}) è \func{UnlockMutex} e serve a
+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 29--32}) la struttura \var{lock} per il
-rilascio del lock, che viene effettuato (\texttt{\small 34}) con la opportuna
+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--40}) è \func{RemoveMutex} e serve a
+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 39}) il file con una chiamata ad \func{unlink}. Si noti che in
+(\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--56}) è \func{ReadMutex} e serve a
-leggere lo stato del mutex. In questo caso si prepara (\texttt{\small 47--50})
+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 52}) la chiamata a \func{fcntl} usando il comando
+(\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 53}) il valore di ritorno in caso di errore, ed il valore del
-campo \var{l\_type} (che descrive lo stato del lock) altrimenti. 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, ed indicare
-che il mutex è, rispettivamente libero o occupato.
-
-
-
-Basandosi sulla semantica dei file lock POSIX valgono tutte le precisazioni
+(\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 che, al contrario di quanto
-avveniva con l'altra interfaccia basata sui semafori, chiamate multiple a
-\func{UnlockMutex} o \func{LockMutex} non hanno nessun inconveniente.
+\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}
@@ -3536,7 +3744,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
@@ -3555,8 +3763,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.
 
 
 
@@ -3570,30 +3779,210 @@ 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 per
+quanto riguarda la memoria condivisa, tutto viene creato nella directory
+\file{/dev/shm}, ed i nomi sono presi come pathname assoluto (comprendente
+eventuali sottodirectory) rispetto a questa radice (per maggiori dettagli si
+veda quanto illustrato in \secref{sec:ipc_posix_shm}). Lo stesso accade per
+l'implementazione sperimentale delle code di messaggi, che però fa riferimento
+alla directory \file{/dev/mqueue}.
+
+Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti
+nell'albero dei file, e possono essere maneggiati con le usuali funzioni e
+comandi di accesso ai file,\footnote{questo è vero nel caso di Linux, che usa
+  una implementazione che lo consente, non è detto che altrettanto valga per
+  altri kernel. In particolare per la memoria condivisa, come si può
+  facilmente evincere con uno \cmd{strace}, le system call utilizzate sono le
+  stesse, in quanto essa è realizzata con file in uno speciale filesystem.}
+che funzionano come su dei file normali.
+
+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 \href{http://www.mat.uni.torun.pl/~wrona/posix_ipc}
+  {http://www.mat.uni.torun.pl/\~{}wrona/posix\_ipc}.}.  In generale, come le
+corrispettive del SysV IPC, le code di messaggi sono poco usate, dato che i
+socket\index{socket}, nei casi in cui sono sufficienti, sono più comodi, e che
+in casi più complessi la comunicazione può essere gestita direttamente con
+mutex e memoria condivisa con tutta la flessibilità che occorre.
+
+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 è \func{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{prototype}
+
+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
+  \errval{EAGAIN}.
+\end{basedescript}
 
+I primi tre bit specificano la modalità di apertura della coda, e sono fra
+loro esclusivi; qualunque sia la modalità in cui si è aperta una coda, questa
+potrà essere riaperta più volte in una modalità diversa, e vi si potrà
+accedere attraverso descrittori diversi, esattamente come si può fare per i
+file normali.
+
+Se la coda non esiste si deve specificare \const{O\_CREAT} per creare una
+nuova, in tal caso come accennato 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 della coda tramite l'argomento
+\param{attr} che è il puntatore ad una struttura \struct{mq\_attr}, la cui
+definizione è riportata in \figref{fig:ipc_mq_attr}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct mq_attr {
+        long    mq_flags;       /* message queue flags                  */
+        long    mq_maxmsg;      /* maximum number of messages           */
+        long    mq_msgsize;     /* maximum message size                 */
+        long    mq_curmsgs;     /* number of messages currently queued  */
+};
+    \end{lstlisting}
+  \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}
+
+Quando si crea la coda possono essere specificati solo i campi
+\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 \errval{EINVAL}.  Qualora si specifichi per
+\param{attr} un puntatore nullo gli attributi della coda saranno impostati ai
+valori predefiniti.
 
 
 \subsection{Semafori}
@@ -3601,16 +3990,50 @@ 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.
+
+
 
 
 \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. Per poterla utilizzare occorre abilitare il filesystem
+\texttt{tmpfs}, uno speciale filesystem che mantiene tutti i suoi contenuti in
+memoria,\footnote{il filesystem \texttt{tmpfs} è diverso da un normale RAM
+  disk, anch'esso disponibile attraverso il filesystem \texttt{ramfs}, proprio
+  perché realizza una interfaccia utilizzabile anche per la memoria condivisa;
+  esso infatti non ha dimensione fissa, ed usa direttamente la cache interna
+  del kernel (viene usato anche per la SysV shared memory). In più i suoi
+  contenuti, essendo trattati direttamente dalla memoria
+  virtuale\index{memoria virtuale} e possono essere salvati sullo swap
+  automaticamente.} abilitando l'opzione \texttt{CONFIG\_TMPFS} in fase di
+compilazione del kernel, e montando il filesystem aggiungendo una riga tipo:
+\begin{verbatim}
+tmpfs   /dev/shm        tmpfs   defaults        0      0
+\end{verbatim}
+ad \file{/etc/fstab}, oppure dove si preferisce con un comando del
+tipo:\footnote{il filesystem riconosce, oltre quelle mostrate, le opzioni
+  \texttt{uid} e \texttt{gid} che identificano rispettivamente utente e gruppo
+  cui assegnarne la titolarità, e \texttt{nr\_blocks} che permette di
+  specificarne la dimensione in blocchi, cioè in multipli di
+  \const{PAGECACHE\_SIZE}.}
+\begin{verbatim}
+mount -t tmpfs -o size=10G,nr_inodes=10k,mode=700 tmpfs /mytmpfs
+\end{verbatim}
+
+
+ la memoria
+condivisa è trattata come un filesystem separato, con tutte le caratteristiche
+di un qualunque filesystem,
 
 
 %%% Local Variables: