Messi gli esempi nel testo e usata daemon dove serve nei server
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 3151c403163487de2b3766617e6253c03baa721b..6f69e46880c4c747a2c4843720657e6e36606658 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -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
@@ -259,7 +259,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 +268,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 +276,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 +287,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 +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 è:
@@ -372,8 +372,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
@@ -436,7 +436,7 @@ int main(int argc, char *argv[], char *envp[])
     };  
     char content[]="Content-type: image/png\n\n";
     int i;
-    /* write mime-type to stout */ 
+    /* write mime-type to stdout */ 
     write(STDOUT_FILENO, content, strlen(content));
     /* execute chain of command */
     for (i=0; i<4; i++) {
@@ -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
@@ -1133,7 +1194,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
@@ -1323,7 +1384,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/}.
 
 
@@ -1371,13 +1432,13 @@ struct msqid_ds {
     \end{lstlisting}
   \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 +1446,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.
@@ -2471,9 +2532,7 @@ nullo per segnalarne l'indisponibilit
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{} 
-/*
- * Function MutexCreate: create a mutex/semaphore
- */
+/* Function MutexCreate: create a mutex/semaphore */
 int MutexCreate(key_t ipc_key) 
 {
     const union semun semunion={1};             /* semaphore union structure */
@@ -2488,23 +2547,17 @@ int MutexCreate(key_t ipc_key)
     }
     return sem_id;
 }
-/*
- * Function MutexFind: get the semaphore/mutex Id given the IPC key value
- */
+/* 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
- */
+/* 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 
- */
+/* 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) */
@@ -2513,19 +2566,20 @@ 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
- */
+/* 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
- */
+/* Function MutexUnlock: to unlock a mutex/semaphore */
 int MutexUnlock(int sem_id) 
 {
     return semop(sem_id, &sem_ulock, 1);
+}
+/* Function MutexRemove: remove a mutex/semaphore */
+int MutexRemove(int sem_id) 
+{
+    return semctl(sem_id, 0, IPC_RMID);
 }
     \end{lstlisting}
   \end{minipage} 
@@ -2535,58 +2589,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
+smemaforo; 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}
@@ -2968,9 +3029,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;    
@@ -2982,8 +3040,7 @@ struct DirProp {
     int tot_block;   
     int tot_char;    
     int tot_sock;
-};
-struct DirProp *shmptr;
+} *shmptr;
 int shmid; 
 int mutex;
 /* main body */
@@ -2996,11 +3053,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");
@@ -3008,12 +3067,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 */
@@ -3029,54 +3090,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, che utilizzaremo per regolare
+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 eseguitw indefinitamente le attività di monitoraggio.
+Il primo passo (\texttt{\small 46}) è esguire \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 print file name and size inside DirScan
- */
+/* Routine  to compute directory properties inside DirScan */
 int ComputeValues(struct dirent * direntry) 
 {
     struct stat data;
@@ -3086,15 +3171,13 @@ int ComputeValues(struct dirent * direntry)
     if (S_ISREG(data.st_mode)) shmptr->tot_regular++;
     if (S_ISFIFO(data.st_mode)) shmptr->tot_fifo++;
     if (S_ISLNK(data.st_mode)) shmptr->tot_link++;
-    if (S_ISDIR(data.st_mode)) shmptr->tot_dir;
-    if (S_ISBLK(data.st_mode)) shmptr->tot_block;
-    if (S_ISCHR(data.st_mode)) shmptr->tot_char;
-    if (S_ISSOCK(data.st_mode)) shmptr->tot_sock;
+    if (S_ISDIR(data.st_mode)) shmptr->tot_dir++;
+    if (S_ISBLK(data.st_mode)) shmptr->tot_block++;
+    if (S_ISCHR(data.st_mode)) shmptr->tot_char++;
+    if (S_ISSOCK(data.st_mode)) shmptr->tot_sock++;
     return 0;
 }
-/*
- * Signal Handler to manage termination
- */
+/* Signal Handler to manage termination */
 void HandSIGTERM(int signo) {
     MutexLock(mutex);
     if (shmdt(shmptr)) {
@@ -3122,28 +3205,177 @@ 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 inoltre (\texttt{\small
-  23--35}) il codice del gestore di segnali usato per terminare il programma,
-che si incarica di cancellare tutti gli oggetti non più necessari. 
+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}{} 
+int main(int argc, char *argv[]) 
+{
+    int i;
+    key_t key;
+    ...
+    /* create needed IPC objects */
+    key = ftok("~/gapil/sources/DirMonitor.c", 1);           /* define a key */
+    shmid = shmget(key, 4096, 0);                /* get the shared memory ID */
+    if (shmid < 0) {
+        perror("Cannot find shared memory");
+        exit(1);
+    }
+    if ( (shmptr = shmat(shmid, NULL, 0)) == NULL ) {   /* attach to process */
+        perror("Cannot attach segment");
+        exit(1);
+    }
+    if ((mutex = MutexFind(key)) == -1) {                   /* get the Mutex */
+        perror("Cannot find mutex");
+        exit(1);
+    }
+    /* main loop */
+    MutexLock(mutex);                                  /* lock shared memory */
+    printf("Ci sono %d file dati\n", shmptr->tot_regular);
+    printf("Ci sono %d directory\n", shmptr->tot_dir);
+    printf("Ci sono %d link\n", shmptr->tot_link);
+    printf("Ci sono %d fifo\n", shmptr->tot_fifo);
+    printf("Ci sono %d socket\n", shmptr->tot_sock);
+    printf("Ci sono %d device a caratteri\n", shmptr->tot_char);
+    printf("Ci sono %d device a blocchi\n", shmptr->tot_block);
+    printf("Totale  %d file, per %d byte\n",
+           shmptr->tot_files, shmptr->tot_size);
+    MutexUnlock(mutex);                              /* unlock shared memory */
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice del programma client del monitori di 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 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 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 libreira 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 (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 intercomunicazion e 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}%$
 
-Anzitutto (\texttt{\small 24}) si acquisisce il mutex per evitare di operare
-mentre un client sta ancora leggendo i dati, dopo di che si distacca
-(\texttt{\small 25--28}) il segmento e lo si cancella (\texttt{\small
-  29--32}). Infine (\texttt{\small 33}) si rimuove il mutex e si esce.
 
 
 %% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
@@ -3192,8 +3424,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}
 
@@ -3273,13 +3503,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
@@ -3291,104 +3521,161 @@ 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)
+/* Function CreateMutex: Create a mutex using file locking. */
+int CreateMutex(const char *path_name)
+{
+    return open(path_name, O_EXCL|O_CREAT);
+}
+/* Function UnlockMutex: unlock a file. */
+int FindMutex(const char *path_name)
+{
+    return open(path_name, O_RDWR);
+}
+/* Function LockMutex: lock mutex using file locking. */
+int LockMutex(int fd)
 {
-    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;
+    return fcntl(fd, F_SETLKW, &lock);
 }
-/*
- * Function UnLockMutex: unlock a file.  
- */
-int UnlockMutex(const char *path_name)
+/* Function UnlockMutex: unlock a file. */
+int UnlockMutex(int fd)
 {
-    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 fcntl(fd, F_SETLK, &lock);
+}
+/* Function RemoveMutex: remove a mutex (unlinking the lock file). */
+int RemoveMutex(const char *path_name)
+{
+    return unlink(path_name);
+}
+/* Function ReadMutex: read a mutex status. */
+int ReadMutex(int fd)
+{
+    int res;
+    struct flock lock;                                /* file lock structure */
+    /* set flock structure */
+    lock.l_type = F_WRLCK;                               /* set type: unlock */
+    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
+    lock.l_start = 0;                  /* set the start of the locked region */
+    lock.l_len = 0;                   /* set the length of the locked region */
+    /* do locking */
+    if ( (res = fcntl(fd, F_GETLK, &lock)) ) {
         return res;
     }
-    return 0;
+    return lock.l_type;
 }
     \end{lstlisting}
   \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.
+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--23}) è \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
+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
+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
+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
+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
+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 solita struttura \var{lock} come l'acquisizione del lock, ma si effettua
+(\texttt{\small 52}) 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, 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 hanno nessun inconveniente.
 
 
 \subsection{Il \textit{memory mapping} anonimo}