Correzioni e commenti ai mutex con il file locking
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index a607aa1f682c800083de6c28a7c96ce2b1f7ed00..4613f8d912cdb0b9d81e4ee8dd5a65f1002906d3 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1,3 +1,13 @@
+%% ipc.tex
+%%
+%% Copyright (C) 2000-2002 Simone Piccardi.  Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Prefazione",
+%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
 \chapter{La comunicazione fra processi}
 \label{cha:IPC}
 
@@ -39,15 +49,15 @@ due file descriptor, nella forma di un \textsl{tubo} (da cui il nome)
 attraverso cui fluiscono i dati.
 
 La funzione che permette di creare questa speciale coppia di file descriptor
-associati ad una \textit{pipe} è appunto \func{pipe}, ed il suo prototipo è:
+associati ad una \textit{pipe} è appunto \funcd{pipe}, ed il suo prototipo è:
 \begin{prototype}{unistd.h}
 {int pipe(int filedes[2])} 
   
 Crea una coppia di file descriptor associati ad una \textit{pipe}.
   
   \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
-    errore, nel qual caso \var{errno} potrà assumere i valori \macro{EMFILE},
-    \macro{ENFILE} e \macro{EFAULT}.}
+    errore, nel qual caso \var{errno} potrà assumere i valori \errval{EMFILE},
+    \errval{ENFILE} e \errval{EFAULT}.}
 \end{prototype}
 
 La funzione restituisce la coppia di file descriptor nel vettore
@@ -56,7 +66,7 @@ accennato concetto di funzionamento di una pipe 
 scrive nel file descriptor aperto in scrittura viene ripresentato tale e quale
 nel file descriptor aperto in lettura. I file descriptor infatti non sono
 connessi a nessun file reale, ma ad un buffer nel kernel, la cui dimensione è
-specificata dalla costante \macro{PIPE\_BUF}, (vedi
+specificata dal parametro di sistema \const{PIPE\_BUF}, (vedi
 \secref{sec:sys_file_limits}). Lo schema di funzionamento di una pipe è
 illustrato in \figref{fig:ipc_pipe_singular}, in cui sono illustrati i due
 capi della pipe, associati a ciascun file descriptor, con le frecce che
@@ -102,11 +112,11 @@ essere bloccante (qualora non siano presenti dati), inoltre se si legge da una
 pipe il cui capo in scrittura è stato chiuso, si avrà la ricezione di un EOF
 (vale a dire che la funzione \func{read} ritornerà restituendo 0).  Se invece
 si esegue una scrittura su una pipe il cui capo in lettura non è aperto il
-processo riceverà il segnale \macro{EPIPE}, e la funzione di scrittura
-restituirà un errore di \macro{EPIPE} (al ritorno del manipolatore, o qualora
-il segnale sia ignorato o bloccato).
+processo riceverà il segnale \errcode{EPIPE}, e la funzione di scrittura
+restituirà un errore di \errcode{EPIPE} (al ritorno del gestore, o qualora il
+segnale sia ignorato o bloccato).
 
-La dimensione del buffer della pipe (\macro{PIPE\_BUF}) ci dà inoltre un'altra
+La dimensione del buffer della pipe (\const{PIPE\_BUF}) ci dà inoltre un'altra
 importante informazione riguardo il comportamento delle operazioni di lettura
 e scrittura su di una pipe; esse infatti sono atomiche fintanto che la
 quantità di dati da scrivere non supera questa dimensione. Qualora ad esempio
@@ -124,7 +134,7 @@ consiste nell'inviare l'output di un processo (lo standard output) sull'input
 di un'altro. Realizzeremo il programma di esempio nella forma di un
 \textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un
   programma che permette la creazione dinamica di un oggetto da inserire
-  all'interno di una pagina HTML.}  per apache, che genera una immagine JPEG
+  all'interno di una pagina HTML.}  per Apache, che genera una immagine JPEG
 di un codice a barre, specificato come parametro di input.
 
 Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
@@ -140,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
@@ -159,13 +169,13 @@ direzione del flusso dei dati 
 Si potrebbe obiettare che sarebbe molto più semplice salvare il risultato
 intermedio su un file temporaneo. Questo però non tiene conto del fatto che un
 \textit{CGI} deve poter gestire più richieste in concorrenza, e si avrebbe una
-evidente race condition in caso di accesso simultaneo a detto
-file.\footnote{il problema potrebbe essere superato determinando in anticipo
-  un nome appropriato per il file temporaneo, che verrebbe utilizzato dai vari
-  sotto-processi, e cancellato alla fine della loro esecuzione; ma a questo le
-  cose non sarebbero più tanto semplici.}  L'uso di una pipe invece permette
-di risolvere il problema in maniera semplice ed elegante, oltre ad essere
-molto più efficiente, dato che non si deve scrivere su disco.
+evidente race condition\index{race condition} in caso di accesso simultaneo a
+detto file.\footnote{il problema potrebbe essere superato determinando in
+  anticipo un nome appropriato per il file temporaneo, che verrebbe utilizzato
+  dai vari sotto-processi, e cancellato alla fine della loro esecuzione; ma a
+  questo le cose non sarebbero più tanto semplici.}  L'uso di una pipe invece
+permette di risolvere il problema in maniera semplice ed elegante, oltre ad
+essere molto più efficiente, dato che non si deve scrivere su disco.
 
 Il programma ci servirà anche come esempio dell'uso delle funzioni di
 duplicazione dei file descriptor che abbiamo trattato in
@@ -249,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
@@ -258,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}).
@@ -266,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
@@ -277,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
@@ -312,7 +322,7 @@ Come si 
 utilizzarla per fare da tramite fra output ed input di due programmi invocati
 in sequenza; per questo motivo lo standard POSIX.2 ha introdotto due funzioni
 che permettono di sintetizzare queste operazioni. La prima di esse si chiama
-\func{popen} ed il suo prototipo è:
+\funcd{popen} ed il suo prototipo è:
 \begin{prototype}{stdio.h}
 {FILE *popen(const char *command, const char *type)}
 
@@ -321,9 +331,9 @@ restituisce, lo standard input o lo standard output nella pipe collegata allo
 stream restituito come valore di ritorno.
   
 \bodydesc{La funzione restituisce l'indirizzo dello stream associato alla pipe
-  in caso di successo e \macro{NULL} per un errore, nel qual caso \var{errno}
+  in caso di successo e \val{NULL} per un errore, nel qual caso \var{errno}
   potrà assumere i valori relativi alle sottostanti invocazioni di \func{pipe}
-  e \func{fork} o \macro{EINVAL} se \param{type} non è valido.}
+  e \func{fork} o \errcode{EINVAL} se \param{type} non è valido.}
 \end{prototype}
 
 La funzione crea una pipe, esegue una \func{fork}, ed invoca il programma
@@ -338,11 +348,11 @@ programma indicato) in caso si sia indicato \code{"r"}, o in sola scrittura (e
 quindi associato allo standard input) in caso di \code{"w"}.
 
 Lo stream restituito da \func{popen} è identico a tutti gli effetti ai file
-stream visti in \secref{cha:files_std_interface}, anche se è collegato ad una
-pipe e non ad un inode, e viene sempre aperto in modalità
+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à
 \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, \func{pclose}, il cui prototipo è:
+funzioni, \funcd{pclose}, il cui prototipo è:
 \begin{prototype}{stdio.h}
 {int pclose(FILE *stream)}
 
@@ -350,7 +360,7 @@ Chiude il file \param{stream}, restituito da una precedente \func{popen}
 attendendo la terminazione del processo ad essa associato.
   
 \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
-  errore; nel quel caso il valore di \func{errno} deriva dalle sottostanti
+  errore; nel quel caso il valore di \var{errno} deriva dalle sottostanti
   chiamate.}
 \end{prototype}
 \noindent che oltre alla chiusura dello stream si incarica anche di attendere
@@ -362,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
@@ -376,12 +386,12 @@ originarie del codice a barre e produce un JPEG di dimensioni corrette.
 Questo approccio però non funziona, per via di una delle caratteristiche
 principali delle pipe. Per poter effettuare la conversione di un PDF infatti è
 necessario, per la struttura del formato, potersi spostare (con \func{lseek})
-all'interno del file da convertire; se si esegue la conversione con \cmd{gs} su
-un file regolare non ci sono problemi, una pipe però è rigidamente
+all'interno del file da convertire; se si esegue la conversione con \cmd{gs}
+su un file regolare non ci sono problemi, una pipe però è rigidamente
 sequenziale, e l'uso di \func{lseek} su di essa fallisce sempre con un errore
-di \macro{ESPIPE}, rendendo impossibile la conversione.  Questo ci dice che in
-generale la concatenazione di vari programmi funzionerà soltanto quando tutti
-prevedono una lettura sequenziale del loro input.
+di \errcode{ESPIPE}, rendendo impossibile la conversione.  Questo ci dice che
+in generale la concatenazione di vari programmi funzionerà soltanto quando
+tutti prevedono una lettura sequenziale del loro input.
 
 Per questo motivo si è dovuto utilizzare un procedimento diverso, eseguendo
 prima la conversione (sempre con \cmd{gs}) del PS in un altro formato
@@ -426,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++) {
@@ -483,15 +493,16 @@ nella relazione padre/figlio; per superare questo problema lo standard POSIX.1
 ha definito dei nuovi oggetti, le \textit{fifo}, che hanno le stesse
 caratteristiche delle pipe, ma che invece di essere strutture interne del
 kernel, visibili solo attraverso un file descriptor, sono accessibili
-attraverso un inode che risiede sul filesystem, così che i processi le possono
-usare senza dovere per forza essere in una relazione di \textsl{parentela}.
+attraverso un inode\index{inode} che risiede sul filesystem, così che i
+processi le possono usare senza dovere per forza essere in una relazione di
+\textsl{parentela}.
 
 Utilizzando una \textit{fifo} tutti i dati passeranno, come per le pipe,
 attraverso un apposito buffer nel kernel, senza transitare dal filesystem;
-l'inode allocato sul filesystem serve infatti solo a fornire un punto di
-riferimento per i processi, che permetta loro di accedere alla stessa fifo; il
-comportamento delle funzioni di lettura e scrittura è identico a quello
-illustrato per le pipe in \secref{sec:ipc_pipes}.
+l'inode\index{inode} allocato sul filesystem serve infatti solo a fornire un
+punto di riferimento per i processi, che permetta loro di accedere alla stessa
+fifo; il comportamento delle funzioni di lettura e scrittura è identico a
+quello illustrato per le pipe in \secref{sec:ipc_pipes}.
 
 Abbiamo già visto in \secref{sec:file_mknod} le funzioni \func{mknod} e
 \func{mkfifo} che permettono di creare una fifo; per utilizzarne una un
@@ -508,7 +519,7 @@ eseguita quando l'altro capo non 
 Le fifo però possono essere anche aperte in modalità \textsl{non-bloccante},
 nel qual caso l'apertura del capo in lettura avrà successo solo quando anche
 l'altro capo è aperto, mentre l'apertura del capo in scrittura restituirà
-l'errore di \macro{ENXIO} fintanto che non verrà aperto il capo in lettura.
+l'errore di \errcode{ENXIO} fintanto che non verrà aperto il capo in lettura.
 
 In Linux è possibile aprire le fifo anche in lettura/scrittura,\footnote{lo
   standard POSIX lascia indefinito il comportamento in questo caso.}
@@ -516,17 +527,17 @@ operazione che avr
 apertura (bloccante e non bloccante); questo può essere utilizzato per aprire
 comunque una fifo in scrittura anche se non ci sono ancora processi il
 lettura; è possibile anche usare la fifo all'interno di un solo processo, nel
-qual caso però occorre stare molto attenti alla possibili
-situazioni di stallo.\footnote{se si cerca di leggere da una fifo che non contiene dati si
-  avrà un deadlock immediato, dato che il processo si blocca e non potrà
-  quindi mai eseguire le funzioni di scrittura.}
+qual caso però occorre stare molto attenti alla possibili situazioni di
+stallo.\footnote{se si cerca di leggere da una fifo che non contiene dati si
+  avrà un deadlock\index{deadlock} immediato, dato che il processo si blocca e
+  non potrà quindi mai eseguire le funzioni di scrittura.}
 
 Per la loro caratteristica di essere accessibili attraverso il filesystem, è
 piuttosto frequente l'utilizzo di una fifo come canale di comunicazione nelle
 situazioni un processo deve ricevere informazioni da altri. In questo caso è
 fondamentale che le operazioni di scrittura siano atomiche; per questo si deve
 sempre tenere presente che questo è vero soltanto fintanto che non si supera
-il limite delle dimensioni di \macro{PIPE\_BUF} (si ricordi quanto detto in
+il limite delle dimensioni di \const{PIPE\_BUF} (si ricordi quanto detto in
 \secref{sec:ipc_pipes}).
 
 A parte il caso precedente, che resta probabilmente il più comune, Stevens
@@ -551,14 +562,14 @@ processo alla volta (nel qual caso basta usare due fifo, una per leggere ed
 una per scrivere), le cose diventano invece molto più complesse quando si
 vuole effettuare una comunicazione fra il server ed un numero imprecisato di
 client; se il primo infatti può ricevere le richieste attraverso una fifo
-``nota'', per le risposte non si può fare altrettanto, dato che, per la
-struttura sequenziale delle fifo, i client dovrebbero sapere, prima di
+``\textsl{nota}'', per le risposte non si può fare altrettanto, dato che, per
+la struttura sequenziale delle fifo, i client dovrebbero sapere, prima di
 leggerli, quando i dati inviati sono destinati a loro.
 
 Per risolvere questo problema, si può usare un'architettura come quella
 illustrata in \figref{fig:ipc_fifo_server_arch} in cui i client inviano le
 richieste al server su una fifo nota mentre le risposte vengono reinviate dal
-server a ciascuno di essi su una fifo temporanea creata per l'occazione.
+server a ciascuno di essi su una fifo temporanea creata per l'occasione.
 
 \begin{figure}[htb]
   \centering
@@ -675,7 +686,7 @@ di end-of-file).
 
 Nel nostro caso la prima apertura si bloccherà fintanto che un qualunque
 client non apre a sua volta la fifo nota in scrittura per effettuare la sua
-richiesta. Pertanto all'inizio non ci sono probelmi, il client però, una volta
+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
@@ -683,7 +694,7 @@ effettuando richieste) con la fifo chiusa sul lato in lettura e a questo punto
 restituendo un end-of-file.\footnote{Si è usata questa tecnica per
   compatibilità, Linux infatti supporta l'apertura delle fifo in
   lettura/scrittura, per cui si sarebbe potuto effettuare una singola apertura
-  con \macro{O\_RDWR}, la doppia apertura comunque ha il vantaggio che non si
+  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
@@ -780,13 +791,12 @@ server che a questo punto non serve pi
 
 Inoltrata la richiesta si può passare alla lettura della risposta; anzitutto
 si apre (\texttt{\small 26--30}) la fifo appena creata, da cui si deve
-riceverla, dopodiché si effettua una lettura (\texttt{\small 31})
+riceverla, dopo di che si effettua una lettura (\texttt{\small 31})
 nell'apposito buffer; si è supposto, come è ragionevole, che le frasi inviate
-dal server siano sempre di dimensioni inferiori a \macro{PIPE\_BUF},
+dal server siano sempre di dimensioni inferiori a \const{PIPE\_BUF},
 tralasciamo la gestione del caso in cui questo non è vero. Infine si stampa
 (\texttt{\small 32}) a video la risposta, si chiude (\texttt{\small 33}) la
 fifo e si cancella (\texttt{\small 34}) il relativo file.
-
 Si noti come la fifo per la risposta sia stata aperta solo dopo aver inviato
 la richiesta, se non si fosse fatto così si avrebbe avuto uno stallo, in
 quanto senza la richiesta, il server non avrebbe potuto aprirne il capo in
@@ -797,7 +807,7 @@ complessa e continua ad avere vari inconvenienti\footnote{lo stesso Stevens,
   che esamina questa architettura in \cite{APUE}, nota come sia impossibile
   per il server sapere se un client è andato in crash, con la possibilità di
   far restare le fifo temporanee sul filesystem, di come sia necessario
-  intercettare \macro{SIGPIPE} dato che un client può terminare dopo aver
+  intercettare \const{SIGPIPE} dato che un client può terminare dopo aver
   fatto una richiesta, ma prima che la risposta sia inviata (cosa che nel
   nostro esempio non è stata fatta).}; in generale infatti l'interfaccia delle
 fifo non è adatta a risolvere questo tipo di problemi, che possono essere
@@ -808,6 +818,68 @@ come quelli che esamineremo in seguito.
 
 
 
+\subsection{La funzione \func{socketpair}}
+\label{sec:ipc_socketpair}
+
+Un meccanismo di comunicazione molto simile alle pipe, ma che non presenta il
+problema della unidirezionalità del flusso dei dati, è quello dei cosiddetti
+\textsl{socket locali} (o \textit{Unix domain socket}). Tratteremo l'argomento
+dei \textit{socket}\index{socket} in \capref{cha:socket_intro},\footnote{si
+  tratta comunque di oggetti di comunicazione che, come le pipe, sono
+  utilizzati attraverso dei file descriptor.} nell'ambito dell'interfaccia
+generale che essi forniscono per la programmazione di rete; e vedremo anche
+(in~\secref{sec:sock_sa_local}) come si possono definire dei file speciali (di
+tipo \textit{socket}, analoghi a quello associati alle fifo) cui si accede
+però attraverso quella medesima interfaccia; vale però la pena esaminare qui
+una modalità di uso dei socket locali\footnote{la funzione \func{socketpair} è
+  stata introdotta in BSD4.4, ma è supportata in genere da qualunque sistema
+  che fornisca l'interfaccia dei socket.} che li rende sostanzialmente
+identici ad una pipe bidirezionale.
+
+La funzione \funcd{socketpair} infatti consente di creare una coppia di file
+descriptor connessi fra di loro (tramite un socket\index{socket}, appunto),
+senza dover ricorrere ad un file speciale sul filesystem, i descrittori sono
+del tutto analoghi a quelli che si avrebbero con una chiamata a \func{pipe},
+con la sola differenza è che in questo caso il flusso dei dati può essere
+effettuato in entrambe le direzioni. Il prototipo della funzione è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/socket.h} 
+  
+  \funcdecl{int socketpair(int domain, int type, int protocol, int sv[2])}
+  
+  Crea una coppia di socket\index{socket} connessi fra loro.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EAFNOSUPPORT}] I socket\index{socket} locali non sono
+    supportati.
+  \item[\errcode{EPROTONOSUPPORT}] Il protocollo specificato non è supportato.
+  \item[\errcode{EOPNOTSUPP}] Il protocollo specificato non supporta la
+  creazione di coppie di socket\index{socket}.
+  \end{errlist}
+  ed inoltre \errval{EMFILE},  \errval{EFAULT}.
+}
+\end{functions}
+
+La funzione restituisce in \param{sv} la coppia di descrittori connessi fra di
+loro: quello che si scrive su uno di essi sarà ripresentato in input
+sull'altro e viceversa. I parametri \param{domain}, \param{type} e
+\param{protocol} derivano dall'interfaccia dei socket\index{socket} (che è
+quella che fornisce il substrato per connettere i due descrittori), ma in
+questo caso i soli valori validi che possono essere specificati sono
+rispettivamente \const{AF\_UNIX}, \const{SOCK\_STREAM} e \val{0}.
+
+L'utilità di chiamare questa funzione per evitare due chiamate a \func{pipe}
+può sembrare limitata; in realtà l'utilizzo di questa funzione (e dei
+socket\index{socket} locali in generale) permette di trasmettere attraverso le
+linea non solo dei dati, ma anche dei file descriptor: si può cioè passare da
+un processo ad un altro un file descriptor, con una sorta di duplicazione
+dello stesso non all'interno di uno stesso processo, ma fra processi distinti
+(torneremo su questa funzionalità in \secref{sec:xxx_fd_passing}).
+
+
 \section{La comunicazione fra processi di System V}
 \label{sec:ipc_sysv}
 
@@ -819,46 +891,52 @@ molti altri devono poter leggere non pu
 Per questo nello sviluppo di System V vennero introdotti una serie di nuovi
 oggetti per la comunicazione fra processi ed una nuova interfaccia di
 programmazione, che fossero in grado di garantire una maggiore flessibilità.
-In questa sezione esamineremo come Linux supporta quello che viene ormai
-chiamato il \textsl{Sistema di comunicazione inter-processo} di System V, o
-\textit{System V IPC (Inter-Process Comunication)}.
+In questa sezione esamineremo come Linux supporta quello che viene chiamato il
+\textsl{Sistema di comunicazione inter-processo} di System V, cui da qui in
+avanti faremo riferimento come \textit{SysV IPC} (dove IPC è la sigla di
+\textit{Inter-Process Comunication}).
 
 
 
 \subsection{Considerazioni generali}
 \label{sec:ipc_sysv_generic}
 
-La principale caratteristica del sistema di IPC di System V è quella di essere
-basato su oggetti permanenti che risiedono nel kernel. Questi, a differenza di
-quanto avviene per i file descriptor, non mantengono un contatore dei
-riferimenti, e non vengono cancellati dal sistema una volta che non sono più
-in uso. 
+La principale caratteristica del \textit{SysV IPC} è quella di essere basato
+su oggetti permanenti che risiedono nel kernel. Questi, a differenza di quanto
+avviene per i file descriptor, non mantengono un contatore dei riferimenti, e
+non vengono cancellati dal sistema una volta che non sono più in uso.
 
 Questo comporta due problemi: il primo è che, al contrario di quanto avviene
 per pipe e fifo, la memoria allocata per questi oggetti non viene rilasciata
-automaticamente quando nessuno li vuole più utilizzare, ed essi devono essere
-cancellati esplicitamente, se non si vuole che restino attivi fino al riavvio
-del sistema. Il secondo è che, dato che non c'è un contatore di riferimenti,
+automaticamente quando non c'è più nessuno che li utilizzi, ed essi devono
+essere cancellati esplicitamente, se non si vuole che restino attivi fino al
+riavvio del sistema. Il secondo problema è che, dato che non c'è, come per i
+file, un contatore del numero di riferimenti che ne indichi l'essere in uso,
 essi possono essere cancellati anche se ci sono dei processi che li stanno
 utilizzando, con tutte le conseguenze (negative) del caso.
 
-Gli oggetti usati nel System V IPC vengono creati direttamente dal kernel, e
-sono accessibili solo specificando il relativo \textsl{identificatore}. Questo
-è un numero progressivo (un po' come il \acr{pid} dei processi) che il kernel
-assegna a ciascuno di essi quanto vengono creati (sul procedimento di
-assegnazione torneremo in \secref{sec:ipc_sysv_id_use}). L'identificatore
-viene restituito dalle funzioni che creano l'oggetto, ed è quindi locale al
-processo che le ha eseguite. Dato che l'identificatore viene assegnato
-dinamicamente dal kernel non è possibile prevedere quale sarà, ne utilizzare
-un qualche valore statico, si pone perciò il problema di come processi diversi
-possono accedere allo stesso oggetto.
-
-Per risolvere il problema il kernel associa a ciascun oggetto una struttura
-\var{ipc\_perm}; questa contiene una \textsl{chiave}, identificata da una
-variabile del tipo primitivo \type{key\_t}, che viene specificata in fase di
-creazione e tramite la quale è possibile ricavare l'identificatore. La
+Un'ulteriore caratteristica negativa è che gli oggetti usati nel \textit{SysV
+  IPC} vengono creati direttamente dal kernel, e sono accessibili solo
+specificando il relativo \textsl{identificatore}. Questo è un numero
+progressivo (un po' come il \acr{pid} dei processi) che il kernel assegna a
+ciascuno di essi quanto vengono creati (sul procedimento di assegnazione
+torneremo in \secref{sec:ipc_sysv_id_use}). L'identificatore viene restituito
+dalle funzioni che creano l'oggetto, ed è quindi locale al processo che le ha
+eseguite. Dato che l'identificatore viene assegnato dinamicamente dal kernel
+non è possibile prevedere quale sarà, né utilizzare un qualche valore statico,
+si pone perciò il problema di come processi diversi possono accedere allo
+stesso oggetto.
+
+Per risolvere il problema nella struttura \struct{ipc\_perm} che il kernel
+associa a ciascun oggetto, viene mantenuto anche un campo apposito che
+contiene anche una \textsl{chiave}, identificata da una variabile del tipo
+primitivo \type{key\_t}, da specificare in fase di creazione dell'oggetto, e
+tramite la quale è possibile ricavare l'identificatore.\footnote{in sostanza
+  si sposta il problema dell'accesso dalla classificazione in base
+  all'identificatore alla classificazione in base alla chiave, una delle tante
+  complicazioni inutili presenti nel \textit{SysV IPC}.} Oltre la chiave, la
 struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm},
-contiene anche le varie proprietà associate all'oggetto. 
+mantiene varie proprietà ed informazioni associate all'oggetto.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -877,7 +955,8 @@ struct ipc_perm
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \var{ipc\_perm}, come definita in \file{sys/ipc.h}.} 
+  \caption{La struttura \structd{ipc\_perm}, come definita in
+    \file{sys/ipc.h}.}
   \label{fig:ipc_ipc_perm}
 \end{figure}
 
@@ -898,20 +977,20 @@ alternativa pi
 la chiave (che ad esempio può essere dichiarato in un header comune), ma c'è
 sempre il rischio che questa chiave possa essere stata già utilizzata da
 qualcun altro.  Dato che non esiste una convenzione su come assegnare queste
-chiavi in maniera univoca l'interfaccia mette a disposizione una funzione,
-\func{ftok}, che permette di ottenere una chiave specificando il nome di un
-file ed un numero di versione; il suo prototipo è:
+chiavi in maniera univoca l'interfaccia mette a disposizione una funzione
+apposita, \funcd{ftok}, che permette di ottenere una chiave specificando il
+nome di un file ed un numero di versione; il suo prototipo è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{sys/ipc.h} 
   
   \funcdecl{key\_t ftok(const char *pathname, int proj\_id)}
   
-  Restituisce una chiave per identificare un oggetto del System V IPC.
+  Restituisce una chiave per identificare un oggetto del \textit{SysV IPC}.
   
   \bodydesc{La funzione restituisce la chiave in caso di successo e -1
-  altrimenti, nel qual caso \var{errno} viene settata ad uno dei possibili
-  codici di errore di \func{stat}.}
+    altrimenti, nel qual caso \var{errno} sarà uno dei possibili codici di
+    errore di \func{stat}.}
 \end{functions}
 
 La funzione determina un valore della chiave sulla base di \param{pathname},
@@ -925,38 +1004,38 @@ significativi.\footnote{nelle libc4 e libc5, come avviene in SunOS,
 
 Il problema è che anche così non c'è la sicurezza che il valore della chiave
 sia univoco, infatti esso è costruito combinando il byte di \param{proj\_id)}
-con i 16 bit meno significativi dell'inode del file \param{pathname} (che
-vengono ottenuti attraverso \func{stat}, da cui derivano i possibili errori),
-e gli 8 bit meno significativi del numero del dispositivo su cui è il file.
-Diventa perciò relativamente facile ottenere delle collisioni, specie se i
-file sono su dispositivi con lo stesso \textit{minor number}, come
-\file{/dev/hda1} e \file{/dev/sda1}.
+con i 16 bit meno significativi dell'inode\index{inode} del file
+\param{pathname} (che vengono ottenuti attraverso \func{stat}, da cui derivano
+i possibili errori), e gli 8 bit meno significativi del numero del dispositivo
+su cui è il file.  Diventa perciò relativamente facile ottenere delle
+collisioni, specie se i file sono su dispositivi con lo stesso \textit{minor
+  number}, come \file{/dev/hda1} e \file{/dev/sda1}.
 
 In genere quello che si fa è utilizzare un file comune usato dai programmi che
-devono comunicare (ad esempio un haeder comune, o uno dei programmi che devono
+devono comunicare (ad esempio un header comune, o uno dei programmi che devono
 usare l'oggetto in questione), utilizzando il numero di progetto per ottenere
 le chiavi che interessano. In ogni caso occorre sempre controllare, prima di
 creare un oggetto, che la chiave non sia già stata utilizzata. Se questo va
 bene in fase di creazione, le cose possono complicarsi per i programmi che
 devono solo accedere, in quanto, a parte gli eventuali controlli sugli altri
-attributi di \var{ipc\_perm}, non esiste una modalità semplice per essere
+attributi di \struct{ipc\_perm}, non esiste una modalità semplice per essere
 sicuri che l'oggetto associato ad una certa chiave sia stato effettivamente
 creato da chi ci si aspetta.
 
 Questo è, insieme al fatto che gli oggetti sono permanenti e non mantengono un
 contatore di riferimenti per la cancellazione automatica, il principale
-problema del sistema di IPC di System V. Non esiste infatti una modalità
-chiara per identificare un oggetto, come sarebbe stato se lo si fosse
-associato ad in file, e tutta l'interfaccia è inutilmente complessa.  Per
-questo ne è stata effettuata una revisione completa nello standard POSIX.1b,
-che tratteremo in \secref{sec:ipc_posix}.
+problema del \textit{SysV IPC}. Non esiste infatti una modalità chiara per
+identificare un oggetto, come sarebbe stato se lo si fosse associato ad in
+file, e tutta l'interfaccia è inutilmente complessa.  Per questo ne è stata
+effettuata una revisione completa nello standard POSIX.1b, che tratteremo in
+\secref{sec:ipc_posix}.
 
 
 \subsection{Il controllo di accesso}
 \label{sec:ipc_sysv_access_control}
 
 Oltre alle chiavi, abbiamo visto che ad ogni oggetto sono associate in
-\var{ipc\_perm} ulteriori informazioni, come gli identificatori del creatore
+\struct{ipc\_perm} ulteriori informazioni, come gli identificatori del creatore
 (nei campi \var{cuid} e \var{cgid}) e del proprietario (nei campi \var{uid} e
 \var{gid}) dello stesso, e un insieme di permessi (nel campo \var{mode}). In
 questo modo è possibile definire un controllo di accesso sugli oggetti di IPC,
@@ -970,16 +1049,16 @@ propriamente un permesso di modifica). I valori di \var{mode} sono gli stessi
 ed hanno lo stesso significato di quelli riportati in
 \secref{tab:file_mode_flags}\footnote{se però si vogliono usare le costanti
   simboliche ivi definite occorrerà includere il file \file{sys/stat.h},
-  alcuni sistemi definiscono le costanti \macro{MSG\_R} (\texttt{0400}) e
-  \macro{MSG\_W} (\texttt{0200}) per indicare i permessi base di lettura e
+  alcuni sistemi definiscono le costanti \const{MSG\_R} (\texttt{0400}) e
+  \const{MSG\_W} (\texttt{0200}) per indicare i permessi base di lettura e
   scrittura per il proprietario, da utilizzare, con gli opportuni shift, pure
   per il gruppo e gli altri, in Linux, visto la loro scarsa utilità, queste
   costanti non sono definite.} e come per i file definiscono gli accessi per
 il proprietario, il suo gruppo e tutti gli altri.
 
 Quando l'oggetto viene creato i campi \var{cuid} e \var{uid} di
-\var{ipc\_perm} ed i campi \var{cgid} e \var{gid} vengono settati
-rispettivamente al valore dell'userid e del groupid effettivo del processo che
+\struct{ipc\_perm} ed i campi \var{cgid} e \var{gid} vengono settati
+rispettivamente al valore dell'user-ID e del group-ID effettivo del processo che
 ha chiamato la funzione, ma, mentre i campi \var{uid} e \var{gid} possono
 essere cambiati, i campi \var{cuid} e \var{cgid} restano sempre gli stessi.
 
@@ -999,12 +1078,12 @@ controlli 
 \begin{itemize}
 \item se il processo ha i privilegi di amministratore l'accesso è sempre
   consentito. 
-\item se l'userid effettivo del processo corrisponde o al valore del campo
+\item se l'user-ID effettivo del processo corrisponde o al valore del campo
   \var{cuid} o a quello del campo \var{uid} ed il permesso per il proprietario
   in \var{mode} è appropriato\footnote{per appropriato si intende che è
     settato il permesso di scrittura per le operazioni di scrittura e quello
     di lettura per le operazioni di lettura.} l'accesso è consentito.
-\item se il groupid effettivo del processo corrisponde o al
+\item se il group-ID effettivo del processo corrisponde o al
   valore del campo \var{cgid} o a quello del campo \var{gid} ed il permesso
   per il gruppo in \var{mode} è appropriato l'accesso è consentito.
 \item se il permesso per gli altri è appropriato l'accesso è consentito.
@@ -1020,7 +1099,7 @@ il valore di \var{umask} (si ricordi quanto esposto in
 \subsection{Gli identificatori ed il loro utilizzo}
 \label{sec:ipc_sysv_id_use}
 
-L'unico campo di \var{ipc\_perm} del quale non abbiamo ancora parlato è
+L'unico campo di \struct{ipc\_perm} del quale non abbiamo ancora parlato è
 \var{seq}, che in \figref{fig:ipc_ipc_perm} è qualificato con un criptico
 ``\textsl{numero di sequenza}'', ne parliamo adesso dato che esso è
 strettamente attinente alle modalità con cui il kernel assegna gli
@@ -1043,18 +1122,18 @@ facciano in tempo ad accorgersi dell'avvenuto, e finiscano con l'interagire
 con gli oggetti del secondo, con conseguenze imprevedibili.
 
 Proprio per evitare questo tipo di situazioni il sistema usa il valore di
-\var{req} per provvedere un meccanismo che porti gli identificatori ad
+\var{seq} per provvedere un meccanismo che porti gli identificatori ad
 assumere tutti i valori possibili, rendendo molto più lungo il periodo in cui
 un identificatore può venire riutilizzato.
 
 Il sistema dispone sempre di un numero fisso di oggetti di IPC,\footnote{fino
-  al kernel 2.2.x questi valori, definiti dalle costanti \macro{MSGMNI},
-  \macro{SEMMNI} e \macro{SHMMNI}, potevano essere cambiati (come tutti gli
-  altri limiti relativi al \textit{System V IPC}) solo con una ricompilazione
-  del kernel, andando a modificarne la definizione nei relativi haeder file.
-  A partire dal kernel 2.4.x è possibile cambiare questi valori a sistema
-  attivo scrivendo sui file \file{shmmni}, \file{msgmni} e \file{sem} di
-  \file{/proc/sys/kernel} o con l'uso di \texttt{syscntl}.} e per ciascuno di
+  al kernel 2.2.x questi valori, definiti dalle costanti \const{MSGMNI},
+  \const{SEMMNI} e \const{SHMMNI}, potevano essere cambiati (come tutti gli
+  altri limiti relativi al \textit{SysV IPC}) solo con una ricompilazione del
+  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 \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
@@ -1062,7 +1141,7 @@ precedenza per restituire l'identificatore al numero di oggetti presenti viene
 sommato il valore di \var{seq} moltiplicato per il numero massimo di oggetti
 di quel tipo,\footnote{questo vale fino ai kernel della serie 2.2.x, dalla
   serie 2.4.x viene usato lo stesso fattore per tutti gli oggetti, esso è dato
-  dalla costante \macro{IPCMNI}, definita in \file{include/linux/ipc.h}, che
+  dalla costante \const{IPCMNI}, definita in \file{include/linux/ipc.h}, che
   indica il limite massimo per il numero di tutti oggetti di IPC, ed il cui
   valore è 32768.}  si evita così il riutilizzo degli stessi numeri, e si fa
 sì che l'identificatore assuma tutti i valori possibili.
@@ -1151,10 +1230,14 @@ mantenuta staticamente all'interno del sistema.
 \subsection{Code di messaggi}
 \label{sec:ipc_sysv_mq}
 
-Il primo oggetto introdotto dal \textit{System V IPC} è quello delle code di
+Il primo oggetto introdotto dal \textit{SysV IPC} è quello delle code di
 messaggi.  Le code di messaggi sono oggetti analoghi alle pipe o alle fifo,
-anche se la loro struttura è diversa. La funzione che permette di ottenerne
-una è \func{msgget} ed il suo prototipo è:
+anche se la loro struttura è diversa, ed il loro scopo principale è appunto
+quello di permettere a processi diversi di scambiarsi dei dati.
+
+La funzione che permette di richiedere al sistema l'identificatore di una coda
+di messaggi esistente (o di crearne una se questa non esiste) è
+\funcd{msgget}; il suo prototipo è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{sys/ipc.h} 
@@ -1162,24 +1245,23 @@ una 
   
   \funcdecl{int msgget(key\_t key, int flag)}
   
-  Restituisce l'identificatore di una cosa di messaggi.
+  Restituisce l'identificatore di una coda di messaggi.
   
   \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
-    in caso di errore, nel qual caso \var{errno} viene settato ad uno dei
-    valori: 
+    in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
-  \item[\macro{EACCES}] Il processo chiamante non ha i privilegi per accedere
+  \item[\errcode{EACCES}] Il processo chiamante non ha i privilegi per accedere
   alla coda richiesta.  
-  \item[\macro{EEXIST}] Si è richiesta la creazione di una coda che già
-  esiste, ma erano specificati sia \macro{IPC\_CREAT} che \macro{IPC\_EXCL}. 
-  \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
-  \item[\macro{ENOENT}] Si è cercato di ottenere l'identificatore di una coda
-    di messaggi specificando una chiave che non esiste e \macro{IPC\_CREAT}
+  \item[\errcode{EEXIST}] Si è richiesta la creazione di una coda che già
+  esiste, ma erano specificati sia \const{IPC\_CREAT} che \const{IPC\_EXCL}. 
+  \item[\errcode{EIDRM}] La coda richiesta è marcata per essere cancellata.
+  \item[\errcode{ENOENT}] Si è cercato di ottenere l'identificatore di una coda
+    di messaggi specificando una chiave che non esiste e \const{IPC\_CREAT}
     non era specificato.
-  \item[\macro{ENOSPC}] Si è cercato di creare una coda di messaggi quando è
-    stato il limite massimo del sistema.
+  \item[\errcode{ENOSPC}] Si è cercato di creare una coda di messaggi quando è
+    stato superato il limite massimo di code (\const{MSGMNI}).
   \end{errlist}
-  ed inoltre \macro{ENOMEM}.
+  ed inoltre \errval{ENOMEM}.
 }
 \end{functions}
 
@@ -1187,33 +1269,34 @@ Le funzione (come le analoghe che si usano per gli altri oggetti) serve sia a
 ottenere l'identificatore di una coda di messaggi esistente, che a crearne una
 nuova. L'argomento \param{key} specifica la chiave che è associata
 all'oggetto, eccetto il caso in cui si specifichi il valore
-\macro{IPC\_PRIVATE}, nel qual caso la coda è creata ex-novo e non vi è
+\const{IPC\_PRIVATE}, nel qual caso la coda è creata ex-novo e non vi è
 associata alcuna chiave, il processo (ed i suoi eventuali figli) potranno
 farvi riferimento solo attraverso l'identificatore.
 
-Se invece si specifica un valore diverso da \macro{IPC\_PRIVATE}\footnote{in
+Se invece si specifica un valore diverso da \const{IPC\_PRIVATE}\footnote{in
   Linux questo significa un valore diverso da zero.} l'effetto della funzione
 dipende dal valore di \param{flag}, se questo è nullo la funzione si limita ad
 effettuare una ricerca sugli oggetti esistenti, restituendo l'identificatore
-se trova una corrispondenza, o fallendo con un errore di \macro{ENOENT} se non
-esiste o di \macro{EACCESS} se si sono specificati dei permessi non validi.
+se trova una corrispondenza, o fallendo con un errore di \errcode{ENOENT} se
+non esiste o di \errcode{EACCES} se si sono specificati dei permessi non
+validi.
 
 Se invece si vuole creare una nuova coda di messaggi \param{flag} non può
 essere nullo e deve essere fornito come maschera binaria, impostando il bit
-corrispondente al valore \macro{IPC\_CREAT}. In questo caso i nove bit meno
+corrispondente al valore \const{IPC\_CREAT}. In questo caso i nove bit meno
 significativi di \param{flag} saranno usati come permessi per il nuovo
 oggetto, secondo quanto illustrato in \secref{sec:ipc_sysv_access_control}.
-Se si imposta anche il bit corrispondente a \macro{IPC\_EXCL} la funzione avrà
+Se si imposta anche il bit corrispondente a \const{IPC\_EXCL} la funzione avrà
 successo solo se l'oggetto non esiste già, fallendo con un errore di
-\macro{EEXIST} altrimenti.
+\errcode{EEXIST} altrimenti.
 
-Si tenga conto che l'uso di \macro{IPC\_PRIVATE} non impedisce ad altri
+Si tenga conto che l'uso di \const{IPC\_PRIVATE} non impedisce ad altri
 processi di accedere alla coda (se hanno privilegi sufficienti) una volta che
 questi possano indovinare o ricavare (ad esempio per tentativi)
 l'identificatore ad essa associato. Per come sono implementati gli oggetti di
 IPC infatti non esiste una maniera che  garantisca l'accesso esclusivo ad una
-coda di messaggi.  Usare \macro{IPC\_PRIVATE} o macro{IPC\_CREAT} e
-\macro{IPC\_EXCL} per \param{flag} comporta solo la creazione di una nuova
+coda di messaggi.  Usare \const{IPC\_PRIVATE} o const{IPC\_CREAT} e
+\const{IPC\_EXCL} per \param{flag} comporta solo la creazione di una nuova
 coda.
 
 \begin{table}[htb]
@@ -1225,22 +1308,22 @@ coda.
     & \textbf{Significato} \\
     \hline
     \hline
-    \macro{MSGMNI}&   16& \file{msgmni} & Numero massimo di code di
+    \const{MSGMNI}&   16& \file{msgmni} & Numero massimo di code di
                                           messaggi. \\
-    \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
+    \const{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
                                           messaggio.\\
-    \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima di una coda di 
-                                          messaggi.\\
+    \const{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di 
+                                          una coda.\\
     \hline
   \end{tabular}
-  \caption{Valori delle costanti associati ai limiti delle code di messaggi.}
+  \caption{Valori delle costanti associate ai limiti delle code di messaggi.}
   \label{tab:ipc_msg_limits}
 \end{table}
 
 Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti
 negli header e corrispondenti alle prime tre costanti riportate in
 \tabref{tab:ipc_msg_limits}, come accennato però in Linux è possibile
-modificare questi limiti attraverso l'uso di \func{syscntl} o scrivendo nei
+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/}.
 
 
@@ -1261,10 +1344,12 @@ Una coda di messaggi 
   nell'accesso casuale e nella ricerca.}  i nuovi messaggi vengono inseriti in
 coda alla lista e vengono letti dalla cima, in \figref{fig:ipc_mq_schema} si è
 riportato lo schema con cui queste strutture vengono mantenute dal
-kernel.\footnote{lo schema illustrato in figura è in realtà una semplificazione
-  di quanto usato fino ai kernel della serie 2.2.x, nei kernel della serie
-  2.4.x la gestione è effettuata in maniera diversa; ma esso illustra comunque
-  in maniera adeguata i principi di funzionamento delle code di messaggi.}
+kernel.\footnote{lo schema illustrato in \figref{fig:ipc_mq_schema} è in
+  realtà una semplificazione di quello usato effettivamente fino ai kernel
+  della serie 2.2.x, nei kernel della serie 2.4.x la gestione delle code di
+  messaggi è stata modificata ed è effettuata in maniera diversa; abbiamo
+  mantenuto lo schema precedente in quanto illustra comunque in maniera più
+  che adeguata i principi di funzionamento delle code di messaggi.}
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1286,34 +1371,52 @@ struct msqid_ds {
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \var{msgid\_ds}, associata a ciascuna coda di
+  \caption{La struttura \structd{msqid\_ds}, associata a ciascuna coda di
     messaggi.}
-  \label{fig:ipc_msgid_sd}
+  \label{fig:ipc_msqid_ds}
 \end{figure}
 
-A ciascuna coda è associata una struttura \var{msgid\_ds}, la cui definizione
-è riportata in \secref{fig:ipc_msgid_sd}, il significato dei vari campi è
-riportato nella figura. In questa struttura il kernel\footnote{come accennato
-  questo vale fino ai kernel della serie 2.2.x, essa viene usata nei kernel
-  della serie 2.4.x solo per compatibilità in quanto è quella restituita dalle
-  funzioni dell'interfaccia.  In \figref{fig:ipc_msgid_sd} sono elencati i
-  campi significativi definiti in \file{sys/msg.h}, a cui si sono agguinti gli
-  ultimi tre campi che sono previsti dalla implementazione originale di System
-  V, ma non dallo standard Unix98.}  mantiene le principali informazioni
-riguardo lo stato corrente della coda.  Quando si crea una nuova coda con
-\func{msgget} questa struttura viene inizializzata, in particolare il campo
-\var{msg\_perm} viene inizializzato come illustrato in
-\secref{sec:ipc_sysv_access_control}, per quanto riguarda gli altri campi
-invece:
+A ciascuna coda è associata una struttura \struct{msgid\_ds}, la cui
+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
+  quanto è quella restituita dalle funzioni dell'interfaccia.  Si noti come ci
+  sia una differenza con i campi mostrati nello schema di
+  \figref{fig:ipc_mq_schema} che sono presi dalla definizione di
+  \file{linux/msg.h}, e fanno riferimento alla definizione della omonima
+  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.
+
+Quando si crea una nuova coda con \func{msgget} questa struttura viene
+inizializzata, in particolare il campo \var{msg\_perm} viene inizializzato
+come illustrato in \secref{sec:ipc_sysv_access_control}, per quanto riguarda
+gli altri campi invece:
 \begin{itemize}
-\item i campi \var{msg\_qnum}, \var{msg\_lspid}, \var{msg\_lrpid},
-  \var{msg\_stime}, \var{msg\_rtime} sono inizializzati a 0
-\item il campo \var{msg\_ctime} viene settato al tempo corrente
-\item il campo \var{msg\_qbytes} al limite di sistema.
+\item il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti
+  sulla coda, viene inizializzato a 0.
+\item i campi \var{msg\_lspid} e \var{msg\_lrpid}, che esprimono
+  rispettivamente il \acr{pid} dell'ultimo processo che ha inviato o ricevuto
+  un messaggio sulla coda, sono inizializzati a 0.
+\item i campi \var{msg\_stime} e \var{msg\_rtime}, che esprimono
+  rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
+  messaggio sulla coda, sono inizializzati a 0.
+\item il campo \var{msg\_ctime}, che esprime il tempo di creazione della coda,
+  viene inizializzato al tempo corrente.
+\item il campo \var{msg\_qbytes} che esprime la dimensione massima del
+  contenuto della coda (in byte) viene inizializzato al valore preimpostato
+  del sistema (\const{MSGMNB}).
+\item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
+  primo e ultimo messaggio sono inizializzati a \val{NULL} e
+  \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
+  inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
+  e non devono essere utilizzati da programmi in user space).
 \end{itemize}
 
 Una volta creata una coda di messaggi le operazioni di controllo vengono
-effettuate con la funzione \func{msgctl}, che (come le analoghe \func{semctl}
+effettuate con la funzione \funcd{msgctl}, che (come le analoghe \func{semctl}
 e \func{shmctl}) fa le veci di quello che \func{ioctl} è per i file; il suo
 prototipo è:
 \begin{functions}
@@ -1326,50 +1429,49 @@ prototipo 
   Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}.
   
   \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
-    errore, nel qual caso \var{errno} viene settato a:
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
-  \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
-    non ha i privilegi di lettura sulla coda.
-  \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
-  \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
+  \item[\errcode{EACCES}] Si è richiesto \const{IPC\_STAT} ma processo
+    chiamante non ha i privilegi di lettura sulla coda.
+  \item[\errcode{EIDRM}] La coda richiesta è stata cancellata.
+  \item[\errcode{EPERM}] Si è richiesto \const{IPC\_SET} o \const{IPC\_RMID} ma
     il processo non ha i privilegi, o si è richiesto di aumentare il valore di
-    \var{msg\_qbytes} oltre il limite \macro{MSGMNB} senza essere
+    \var{msg\_qbytes} oltre il limite \const{MSGMNB} senza essere
     amministratore.
   \end{errlist}
-  ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+  ed inoltre \errval{EFAULT} ed \errval{EINVAL}.
 }
 \end{functions}
 
-La funzione permette di accedere ai valori della struttura \var{msqid\_ds},
+La funzione permette di accedere ai valori della struttura \struct{msqid\_ds},
 mantenuta all'indirizzo \param{buf}, per la coda specificata
 dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
 valore dell'argomento \param{cmd}, che specifica il tipo di azione da
 eseguire; i valori possibili sono:
-\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}}
-\item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{IPC\_STAT}] Legge le informazioni riguardo la coda nella
   struttura indicata da \param{buf}. Occorre avere il permesso di lettura
   sulla coda.
-\item[\macro{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con
+\item[\const{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con
   effetto immediato. Tutti i processi che cercheranno di accedere alla coda
-  riceveranno un errore di \macro{EIDRM}, e tutti processi in attesa su
+  riceveranno un errore di \errcode{EIDRM}, e tutti processi in attesa su
   funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo
   il medesimo errore. Questo comando può essere eseguito solo da un processo
-  con userid effettivo corrispondente al creatore a o al proprietario della
+  con user-ID effettivo corrispondente al creatore o al proprietario della
   coda, o all'amministratore.
-\item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+\item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario
   della coda, ed il limite massimo sulle dimensioni del totale dei messaggi in
   essa contenuti (\var{msg\_qbytes}). I valori devono essere passati in una
-  struttura \var{msqid\_ds} puntata da \param{buf}.  Per modificare i valori
+  struttura \struct{msqid\_ds} puntata da \param{buf}.  Per modificare i valori
   di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid} occorre
   essere il proprietario o il creatore della coda, oppure l'amministratore; lo
-  stesso vale per \var{msg\_qbytes}, con la restrizione che solo
-  l'amministratore può incrementarne il valore a limiti superiori a
-  \macro{MSGMNB}.
+  stesso vale per \var{msg\_qbytes}, ma l'amministratore ha la facoltà di
+  incrementarne il valore a limiti superiori a \const{MSGMNB}.
 \end{basedescript}
 
 
 Una volta che si abbia a disposizione l'identificatore, per inviare un
-messaggio su una coda si utilizza la funzione \func{msgsnd}; il suo prototipo
+messaggio su una coda si utilizza la funzione \funcd{msgsnd}; il suo prototipo
 è:
 \begin{functions}
   \headdecl{sys/types.h} 
@@ -1382,64 +1484,75 @@ messaggio su una coda si utilizza la funzione \func{msgsnd}; il suo prototipo
   Invia un messaggio sulla coda \param{msqid}.
   
   \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso
-    \var{errno} viene settata a:
+    \var{errno} assumerà uno dei valori:
   \begin{errlist}
-  \item[\macro{EACCES}] Non si hanno i privilegi di accesso sulla coda.
-  \item[\macro{EIDRM}] La coda è stata cancellata.
-  \item[\macro{EAGAIN}] Il messaggio non può essere inviato perché si è
+  \item[\errcode{EACCES}] Non si hanno i privilegi di accesso sulla coda.
+  \item[\errcode{EIDRM}] La coda è stata cancellata.
+  \item[\errcode{EAGAIN}] Il messaggio non può essere inviato perché si è
   superato il limite \var{msg\_qbytes} sul numero massimo di byte presenti
-  sulla coda, e si è richiesto \macro{IPC\_NOWAIT} in \param{flag}.
-  \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
-  \item[\macro{EINVAL}] Si è specificato un \param{msgid} invalido, o un
+  sulla coda, e si è richiesto \const{IPC\_NOWAIT} in \param{flag}.
+  \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+  \item[\errcode{EINVAL}] Si è specificato un \param{msgid} invalido, o un
     valore non positivo per \param{mtype}, o un valore di \param{msgsz}
-    maggiore di \macro{MSGMAX}.
+    maggiore di \const{MSGMAX}.
   \end{errlist}
-  ed inoltre \macro{EFAULT} ed \macro{ENOMEM}.
+  ed inoltre \errval{EFAULT} ed \errval{ENOMEM}.
 }
 \end{functions}
 
 La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
-messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso
-l'argomento \param{msgp}.  Quest'ultimo deve venire passato sempre in una
-forma che corrisponda alla struttura \var{msgbuf} riportata in
-\figref{fig:ipc_msbug}.  La struttura è solo un modello, la sola cosa che
-conta è abbia come primo membro un campo \var{mtype}, come nell'esempio; esso
-infatti serve ad identificare il tipo di messaggio e deve essere sempre
-specificato come intero positivo.  Il campo \var{mtext} invece può essere di
-qualsiasi tipo e dimensione, e deve contenere il testo del messaggio.
-
-In generale pertanto occorrerà ridefinire una struttura analoga a quella di
-\figref{fig:ipc_msbug}, adattando alle proprie esigenze il campo \var{mtype},
-e avendo cura di mantenere come primo campo un valore di tipo \ctyp{long}. Il
-resto della struttura andrà a costituire il corpo del messaggio, la cui
-dimensione deve essere specificata sempre attraverso \param{msgsz}. Si tenga
-presente che la lunghezza che deve essere indicata in questo argomento è solo
-quella del messaggio, non di tutta la struttura, se cioè \var{message} è la
-struttura che si passa alla funzione, \param{msgsz} dovrà essere uguale a
-\code{sizeof(message)-sizeof(long)}.
+messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso il
+l'argomento \param{msgp}.  Quest'ultimo deve venire passato sempre come
+puntatore ad una struttura \struct{msgbuf} analoga a quella riportata in
+\figref{fig:ipc_msbuf} che è quella che deve contenere effettivamente il
+messaggio.  La dimensione massima per il testo di un messaggio non può
+comunque superare il limite \const{MSGMAX}.
+
+La struttura di \figref{fig:ipc_msbuf} è comunque solo un modello, tanto che
+la definizione contenuta in \file{sys/msg.h} usa esplicitamente per il secondo
+campo il valore \code{mtext[1]}, che non è di nessuna utilità ai fini pratici.
+La sola cosa che conta è che la struttura abbia come primo membro un campo
+\var{mtype} come nell'esempio; esso infatti serve ad identificare il tipo di
+messaggio e deve essere sempre specificato come intero positivo di tipo
+\ctyp{long}.  Il campo \var{mtext} invece può essere di qualsiasi tipo e
+dimensione, e serve a contenere il testo del messaggio.
+
+In generale pertanto per inviare un messaggio con \func{msgsnd} si usa
+ridefinire una struttura simile a quella di \figref{fig:ipc_msbuf}, adattando
+alle proprie esigenze il campo \var{mtype}, (o ridefinendo come si vuole il
+corpo del messaggio, anche con più campi o con strutture più complesse) avendo
+però la cura di mantenere nel primo campo un valore di tipo \ctyp{long} che ne
+indica il tipo.
+
+Si tenga presente che la lunghezza che deve essere indicata in questo
+argomento è solo quella del messaggio, non quella di tutta la struttura, se
+cioè \var{message} è una propria struttura che si passa alla funzione,
+\param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se
+consideriamo il caso dell'esempio in \figref{fig:ipc_msbuf}, \param{msgsz}
+dovrà essere pari a \const{LENGTH}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}[labelstep=0]{}
     struct msgbuf {
-         long mtype;     /* message type, must be > 0 */
-         char mtext[1];  /* message data */
+         long mtype;          /* message type, must be > 0 */
+         char mtext[LENGTH];  /* message data */
     };
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{Schema della struttura \var{msgbug}, da utilizzare come argomento
-    per inviare/ricevere messaggi.}
-  \label{fig:ipc_msbug}
+  \caption{Schema della struttura \structd{msgbuf}, da utilizzare come
+    argomento per inviare/ricevere messaggi.}
+  \label{fig:ipc_msbuf}
 \end{figure}
 
 Per capire meglio il funzionamento della funzione riprendiamo in
 considerazione la struttura della coda illustrata in
-\secref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
-sarà aggiunto in fondo alla lista inserendo una nuova struttura \var{msg}, il
-puntatore \var{msg\_last} di \var{msqid\_ds} verrà aggiornato, come pure il
-puntatore al messaggio successivo per quello che era il precedente ultimo
+\figref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
+sarà aggiunto in fondo alla lista inserendo una nuova struttura \struct{msg},
+il puntatore \var{msg\_last} di \struct{msqid\_ds} verrà aggiornato, come pure
+il puntatore al messaggio successivo per quello che era il precedente ultimo
 messaggio; il valore di \var{mtype} verrà mantenuto in \var{msg\_type} ed il
 valore di \param{msgsz} in \var{msg\_ts}; il testo del messaggio sarà copiato
 all'indirizzo specificato da \var{msg\_spot}.
@@ -1449,30 +1562,29 @@ della funzione. Di norma, quando si specifica un valore nullo, la funzione
 ritorna immediatamente a meno che si sia ecceduto il valore di
 \var{msg\_qbytes}, o il limite di sistema sul numero di messaggi, nel qual
 caso si blocca mandando il processo in stato di \textit{sleep}.  Se si
-specifica per \param{flag} il valore \macro{IPC\_NOWAIT} la funzione opera in
+specifica per \param{flag} il valore \const{IPC\_NOWAIT} la funzione opera in
 modalità non bloccante, ed in questi casi ritorna immediatamente con un errore
-di \macro{EAGAIN}.
+di \errcode{EAGAIN}.
 
-Se non si specifica \macro{IPC\_NOWAIT} la funzione resterà bloccata fintanto
+Se non si specifica \const{IPC\_NOWAIT} la funzione resterà bloccata fintanto
 che non si liberano risorse sufficienti per poter inserire nella coda il
 messaggio, nel qual caso ritornerà normalmente. La funzione può ritornare, con
 una condizione di errore anche in due altri casi: quando la coda viene rimossa
-(nel qual caso si ha un errore di \macro{EIDRM}) o quando la funzione viene
-interrotta da un segnale (nel qual caso si ha un errore di \macro{EINTR}).
+(nel qual caso si ha un errore di \errcode{EIDRM}) o quando la funzione viene
+interrotta da un segnale (nel qual caso si ha un errore di \errcode{EINTR}).
 
 Una volta completato con successo l'invio del messaggio sulla coda, la
-funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
-modificati:
+funzione aggiorna i dati mantenuti in \struct{msqid\_ds}, in particolare
+vengono modificati:
 \begin{itemize*}
-\item Il valore di \var{msg\_lspid}, che viene importato al \acr{pid} del
+\item Il valore di \var{msg\_lspid}, che viene impostato al \acr{pid} del
   processo chiamante.
 \item Il valore di \var{msg\_qnum}, che viene incrementato di uno.
 \item Il valore \var{msg\_stime}, che viene impostato al tempo corrente.
 \end{itemize*}
 
-
-La funzione che permette di estrarre da una coda un messaggio (che sarà
-rimosso dalla stessa) è \func{msgrcv}; il suo prototipo è:
+La funzione che viene utilizzata per estrarre un messaggio da una coda è
+\funcd{msgrcv}; il suo prototipo è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{sys/ipc.h} 
@@ -1484,43 +1596,337 @@ rimosso dalla stessa) 
   Legge un messaggio dalla coda \param{msqid}.
   
   \bodydesc{La funzione restituisce il numero di byte letti in caso di
-    successo, e -1 in caso di errore, nel qual caso \var{errno} viene settata
-    a:
+    successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà uno
+    dei valori:
   \begin{errlist}
-  \item[\macro{EACCES}] Non si hanno i privilegi di accesso sulla coda.
-  \item[\macro{EIDRM}] La coda è stata cancellata.
-  \item[\macro{E2BIG}] Il testo del messaggio è più lungo di \param{msgsz} e
-  non si è specificato \macro{MSG\_NOERROR} in \param{msgflg}.
-  \item[\macro{EINTR}] La funzione è stata interrotta da un segnale mentre era
-  in attesa di ricevere un messaggio.
-  \item[\macro{EINVAL}] Si è specificato un \param{msgid} invalido o un valore
-    di \param{msgsz} negativo.
+  \item[\errcode{EACCES}] Non si hanno i privilegi di accesso sulla coda.
+  \item[\errcode{EIDRM}] La coda è stata cancellata.
+  \item[\errcode{E2BIG}] Il testo del messaggio è più lungo di \param{msgsz} e
+    non si è specificato \const{MSG\_NOERROR} in \param{msgflg}.
+  \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale mentre
+    era in attesa di ricevere un messaggio.
+  \item[\errcode{EINVAL}] Si è specificato un \param{msgid} invalido o un
+    valore di \param{msgsz} negativo.
   \end{errlist}
-  ed inoltre \macro{EFAULT}.
+  ed inoltre \errval{EFAULT}.
 }
 \end{functions}
 
-La funzione è analoga alla precedente \func{msgsnd} ed gli argomenti sono
-analoghi, con l'eccezione di \param{type}, questo permette di restringere la
-ricerca ad alcuni messaggi; in particolare:
-\begin{itemize}
-\item se \param{type} è 0 viene estratto il messaggio in cima alla coda (cioè
-  quello fra i presenti che è stato inserito inserito per primo). 
-\item se \param{type} è positivo viene estratto il primo messaggio il cui tipo
-  (il valore del campo \var{mtype}) corrisponde a quanto specificato.
-\item se \param{type} è negativo viene estratto il primo messaggio il valore
-  di tipo più basso inferiore al valore assoluto di quanto specificato.
-\end{itemize}
+La funzione legge un messaggio dalla coda specificata, scrivendolo sulla
+struttura puntata da \param{msgp}, che dovrà avere un formato analogo a quello
+di \figref{fig:ipc_msbuf}.  Una volta estratto, il messaggio sarà rimosso dalla
+coda.  L'argomento \param{msgsz} indica la lunghezza massima del testo del
+messaggio (equivalente al valore del parametro \const{LENGTH} nell'esempio di
+\figref{fig:ipc_msbuf}).
+
+Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene
+rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a
+\const{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene
+perduta, altrimenti il messaggio non viene estratto e la funzione ritorna con
+un errore di \errcode{E2BIG}.
+
+L'argomento \param{msgtyp} permette di restringere la ricerca ad un
+sottoinsieme dei messaggi presenti sulla coda; la ricerca infatti è fatta con
+una scansione della struttura mostrata in \figref{fig:ipc_mq_schema},
+restituendo il primo messaggio incontrato che corrisponde ai criteri
+specificati (che quindi, visto come i messaggi vengono sempre inseriti dalla
+coda, è quello meno recente); in particolare:
+\begin{itemize*}
+\item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè
+  quello fra i presenti che è stato inserito inserito per primo. 
+\item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui
+  tipo (il valore del campo \var{mtype}) corrisponde al valore di
+  \param{msgtyp}.
+\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*}
+
+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ù
+valori.  Oltre al precedente \const{MSG\_NOERROR}, sono possibili altri due
+valori: \const{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo,
+di leggere il primo messaggio nella coda con tipo diverso da \param{msgtyp}, e
+\const{IPC\_NOWAIT} che causa il ritorno immediato della funzione quando non
+ci sono messaggi sulla coda.
+
+Il comportamento usuale della funzione infatti, se non ci sono messaggi
+disponibili per la lettura, è di bloccare il processo in stato di
+\textit{sleep}. Nel caso però si sia specificato \const{IPC\_NOWAIT} la
+funzione ritorna immediatamente con un errore \errcode{ENOMSG}. Altrimenti la
+funzione ritorna normalmente non appena viene inserito un messaggio del tipo
+desiderato, oppure ritorna con errore qualora la coda sia rimossa (con
+\var{errno} impostata a \errcode{EIDRM}) o se il processo viene interrotto da
+un segnale (con \var{errno} impostata a \errcode{EINTR}).
+
+Una volta completata con successo l'estrazione del messaggio dalla coda, la
+funzione aggiorna i dati mantenuti in \struct{msqid\_ds}, in particolare
+vengono modificati:
+\begin{itemize*}
+\item Il valore di \var{msg\_lrpid}, che viene impostato al \acr{pid} del
+  processo chiamante.
+\item Il valore di \var{msg\_qnum}, che viene decrementato di uno.
+\item Il valore \var{msg\_rtime}, che viene impostato al tempo corrente.
+\end{itemize*}
+
+Le code di messaggi presentano il solito problema di tutti gli oggetti del
+SysV IPC; essendo questi permanenti restano nel sistema occupando risorse
+anche quando un processo è terminato, al contrario delle pipe per le quali
+tutte le risorse occupate vengono rilasciate quanto l'ultimo processo che le
+utilizzava termina. Questo comporta che in caso di errori si può saturare il
+sistema, e che devono comunque essere esplicitamente previste delle funzioni
+di rimozione in caso di interruzioni o uscite dal programma (come vedremo in
+\figref{fig:ipc_mq_fortune_server}).
+
+L'altro problema è non facendo uso di file descriptor le tecniche di
+\textit{I/O multiplexing} descritte in \secref{sec:file_multiplexing} non
+possono essere utilizzate, e non si ha a disposizione niente di analogo alle
+funzioni \func{select} e \func{poll}. Questo rende molto scomodo usare più di
+una di queste strutture alla volta; ad esempio non si può scrivere un server
+che aspetti un messaggio su più di una coda senza fare ricorso ad una tecnica
+di \textit{polling}\index{polling} che esegua un ciclo di attesa su ciascuna
+di esse.
+
+Come esempio dell'uso delle code di messaggi possiamo riscrivere il nostro
+server di \textit{fortunes} usando queste al posto delle fifo. In questo caso
+useremo una sola coda di messaggi, usando il tipo di messaggio per comunicare
+in maniera indipendente con client diversi.
+
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int msgid;                                       /* Message queue identifier */
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+    int i, n = 0;
+    char **fortune;                       /* array of fortune message string */
+    char *fortunefilename;                              /* fortune file name */
+    struct msgbuf_read {      /* message struct to read request from clients */
+        long mtype;                               /* message type, must be 1 */
+        long pid;             /* message data, must be the pid of the client */
+    } msg_read;
+    struct msgbuf_write {       /* message struct to write result to clients */
+        long mtype;            /* message type, will be the pid of the client*/
+        char mtext[MSGMAX];             /* message data, will be the fortune */
+    } msg_write;
+    key_t key;                                          /* Message queue key */
+    int size;                                                /* message size */
+    ...
+    Signal(SIGTERM, HandSIGTERM);            /* set handlers for termination */
+    Signal(SIGINT, HandSIGTERM);
+    Signal(SIGQUIT, HandSIGTERM);
+    if (n==0) usage();          /* if no pool depth exit printing usage info */
+    i = FortuneParse(fortunefilename, fortune, n);          /* parse phrases */
+    /* Create the queue */
+    key = ftok("./MQFortuneServer.c", 1); 
+    msgid = msgget(key, IPC_CREAT|0666);
+    if (msgid < 0) {
+        perror("Cannot create message queue");
+        exit(1);
+    }
+    /* Main body: loop over requests */
+    while (1) {
+        msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR);
+        n = random() % i;                             /* select random value */
+        strncpy(msg_write.mtext, fortune[n], MSGMAX);
+        size = min(strlen(fortune[n])+1, MSGMAX);  
+        msg_write.mtype=msg_read.pid;             /* use request pid as type */
+        msgsnd(msgid, &msg_write, size, 0);
+    }
+}
+/*
+ * Signal Handler to manage termination
+ */
+void HandSIGTERM(int signo) {
+    msgctl(msgid, IPC_RMID, NULL);                   /* remove message queue */
+    exit(0);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del server di \textit{fortunes}
+    basato sulle \textit{message queue}.}
+  \label{fig:ipc_mq_fortune_server}
+\end{figure}
+
+In \figref{fig:ipc_mq_fortune_server} si è riportato un estratto delle parti
+principali del codice del nuovo server (il codice completo è nel file
+\file{MQFortuneServer.c} nei sorgenti allegati). Il programma è basato su un
+uso accorto della caratteristica di poter associate un ``tipo'' ai messaggi
+per permettere una comunicazione indipendente fra il server ed i vari client,
+usando il \acr{pid} di questi ultimi come identificativo. Questo è possibile
+in quanto, al contrario di una fifo, la lettura di una coda di messaggi può
+non essere sequenziale, proprio grazie alla classificazione dei messaggi sulla
+base del loro tipo.
+
+Il programma, oltre alle solite variabili per il nome del file da cui leggere
+le \textit{fortunes} e per il vettore di stringhe che contiene le frasi,
+definisce due strutture appositamente per la comunicazione; con
+\var{msgbuf\_read} (\texttt{\small 8--11}) vengono passate le richieste mentre
+con \var{msgbuf\_write} (\texttt{\small 12--15}) vengono restituite le frasi.
+
+La gestione delle opzioni si è al solito omessa, essa si curerà di impostare
+in \var{n} il numero di frasi da leggere specificato a linea di comando ed in
+\var{fortunefilename} il file da cui leggerle; dopo aver installato
+(\texttt{\small 19--21}) i gestori dei segnali per trattare l'uscita dal
+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.
+
+Una volta inizializzato il vettore di stringhe coi messaggi presi dal file
+delle \textit{fortune} si procede (\texttt{\small 25}) con la generazione di
+una chiave per identificare la coda di messaggi (si usa il nome del file dei
+sorgenti del server) con la quale poi si esegue (\texttt{\small 26}) la
+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).
+
+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.
+
+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})
+al valore del \acr{pid} del client ricevuto nel messaggio di richiesta.
+L'ultimo passo del ciclo (\texttt{\small 38}) è 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}).
+
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int main(int argc, char *argv[])
+{
+    ...
+    key = ftok("./MQFortuneServer.c", 1); 
+    msgid = msgget(key, 0); 
+    if (msgid < 0) {
+        perror("Cannot find message queue");
+        exit(1);
+    }
+    /* Main body: do request and write result */
+    msg_read.mtype = 1;                      /* type for request is always 1 */
+    msg_read.pid = getpid();                   /* use pid for communications */
+    size = sizeof(msg_read.pid);  
+    msgsnd(msgid, &msg_read, size, 0);               /* send request message */
+    msgrcv(msgid, &msg_write, MSGMAX, msg_read.pid, MSG_NOERROR);
+    printf("%s", msg_write.mtext);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione principale del codice del client di \textit{fortunes}
+    basato sulle \textit{message queue}.}
+  \label{fig:ipc_mq_fortune_client}
+\end{figure}
+
+In \figref{fig:ipc_mq_fortune_client} si è riportato un estratto il codice del
+programma client.  Al solito il codice completo è con i sorgenti allegati, nel
+file \file{MQFortuneClient.c}.  Come sempre si sono rimosse le parti relative
+alla gestione delle opzioni, ed in questo caso, anche la dichiarazione delle
+variabili, che, per la parte relative alle strutture usate per la
+comunicazione tramite le code, sono le stesse viste in
+\figref{fig:ipc_mq_fortune_server}.
+
+Il client in questo caso è molto semplice; la prima parte del programma
+(\texttt{\small 4--9}) si occupa di accedere alla coda di messaggi, ed è
+identica a quanto visto per il server, solo che in questo caso \func{msgget}
+non viene chiamata con il flag di creazione in quanto la coda deve essere
+preesistente. In caso di errore (ad esempio se il server non è stato avviato)
+il programma termina immediatamente. 
+
+Una volta acquisito l'identificatore della coda il client compone il
+messaggio di richiesta (\texttt{\small 12--13}) in \var{msg\_read}, usando 1
+per il tipo ed inserendo il proprio \acr{pid} come dato da passare al server.
+Calcolata (\texttt{\small 14}) la dimensione, provvede (\texttt{\small 15}) ad
+immettere la richiesta sulla coda. 
+
+A questo punto non resta che (\texttt{\small 16}) rileggere dalla coda la
+risposta del server richiedendo a \func{msgrcv} di selezionare i messaggi di
+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.
+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
+della risposta, quest'ultima resta nella coda (così come per le fifo si aveva
+il problema delle fifo che restavano nel filesystem). In questo caso però il
+problemi sono maggiori, sia perché è molto più facile esaurire la memoria
+dedicata ad una coda di messaggi che gli inode\index{inode} di un filesystem,
+sia perché, con il riutilizzo dei \acr{pid} da parte dei processi, un client
+eseguito in un momento successivo potrebbe ricevere un messaggio non
+indirizzato a lui.
 
 
 
 \subsection{Semafori}
 \label{sec:ipc_sysv_sem}
 
-Il secondo oggetto introdotto dal \textit{System V IPC} è quello dei semafori.
-Un semaforo è uno speciale contatore che permette di controllare l'accesso a
-risorse condivise. La funzione che permette di ottenere un insieme di semafori
-è \func{semget} ed il suo prototipo è:
+I semafori non sono meccanismi di intercomunicazione diretta come quelli
+(pipe, fifo e code di messaggi) visti finora, e non consentono di scambiare
+dati fra processi, ma servono piuttosto come meccanismi di sincronizzazione o
+di protezione per le \textsl{sezioni critiche}\index{sezioni critiche} del
+codice (si ricordi quanto detto in \secref{sec:proc_race_cond}). 
+
+Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a
+seconda del suo valore, di consentire o meno la prosecuzione dell'esecuzione
+di un programma. In questo modo l'accesso ad una risorsa condivisa da più
+processi può essere controllato, associando ad essa un semaforo che consente
+di assicurare che non più di un processo alla volta possa usarla.
+
+Il concetto di semaforo è uno dei concetti base nella programmazione ed è
+assolutamente generico, così come del tutto generali sono modalità con cui lo
+si utilizza. Un processo che deve accedere ad una risorsa eseguirà un
+controllo del semaforo: se questo è positivo il suo valore sarà decrementato,
+indicando che si è consumato una unità della risorsa, ed il processo potrà
+proseguire nell'utilizzo di quest'ultima, provvedendo a rilasciarla, una volta
+completate le operazioni volute, reincrementando il semaforo.
+
+Se al momento del controllo il valore del semaforo è nullo, siamo invece in
+una situazione in cui la risorsa non è disponibile, ed il processo si
+bloccherà in stato di \textit{sleep} fin quando chi la sta utilizzando non la
+rilascerà, incrementando il valore del semaforo. Non appena il semaforo torna
+positivo, indicando che la risorsa è disponibile, il processo sarà svegliato,
+e si potrà operare come nel caso precedente (decremento del semaforo, accesso
+alla risorsa, incremento del semaforo).
+
+Per poter implementare questo tipo di logica le operazioni di controllo e
+decremento del contatore associato al semaforo devono essere atomiche,
+pertanto una realizzazione di un oggetto di questo tipo è necessariamente
+demandata al kernel. La forma più semplice di semaforo è quella del
+\textsl{semaforo binario}, o \textit{mutex}, in cui un valore diverso da zero
+(normalmente 1) indica la libertà di accesso, e un valore nullo l'occupazione
+della risorsa; in generale però si possono usare semafori con valori interi,
+utilizzando il valore del contatore come indicatore del ``numero di risorse''
+ancora disponibili.
+
+Il sistema di comunicazione inter-processo di \textit{SysV IPC} prevede anche i
+semafori, ma gli oggetti utilizzati non sono semafori singoli, ma gruppi di
+semafori detti \textsl{insiemi} (o \textit{semaphore set}); la funzione che
+permette di creare o ottenere l'identificatore di un insieme di semafori è
+\funcd{semget}, ed il suo prototipo è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{sys/ipc.h} 
@@ -1528,28 +1934,666 @@ risorse condivise. La funzione che permette di ottenere un insieme di semafori
   
   \funcdecl{int semget(key\_t key, int nsems, int flag)}
   
-  Restituisce l'identificatore di un semaforo.
+  Restituisce l'identificatore di un insieme di semafori.
   
   \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
-    in caso di errore, nel qual caso \var{errno} viene settato agli stessi
-    valori visti per \func{msgget}.}
+    in caso di errore, nel qual caso \var{errno} assumerà i valori:
+    \begin{errlist}
+    \item[\errcode{ENOSPC}] Si è cercato di creare una insieme di semafori
+      quando è stato superato o il limite per il numero totale di semafori
+      (\const{SEMMNS}) o quello per il numero totale degli insiemi
+      (\const{SEMMNI}) nel sistema.
+    \item[\errcode{EINVAL}] L'argomento \param{nsems} è minore di zero o
+      maggiore del limite sul numero di semafori per ciascun insieme
+      (\const{SEMMSL}), o se l'insieme già esiste, maggiore del numero di
+      semafori che contiene.
+    \item[\errcode{ENOMEM}] Il sistema non ha abbastanza memoria per poter
+      contenere le strutture per un nuovo insieme di semafori.
+    \end{errlist}
+    ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST},
+    \errval{EIDRM}, con lo stesso significato che hanno per \func{msgget}.}
+\end{functions}
+
+La funzione è del tutto analoga a \func{msgget}, solo che in questo caso
+restituisce l'identificatore di un insieme di semafori, in particolare è
+identico l'uso degli argomenti \param{key} e \param{flag}, per cui non
+ripeteremo quanto detto al proposito in \secref{sec:ipc_sysv_mq}. L'argomento
+\param{nsems} permette di specificare quanti semafori deve contenere l'insieme
+quando se ne richieda la creazione, e deve essere nullo quando si effettua una
+richiesta dell'identificatore di un insieme già esistente.
+
+Purtroppo questa implementazione complica inutilmente lo schema elementare che
+abbiamo descritto, dato che non è possibile definire un singolo semaforo, ma
+se ne deve creare per forza un insieme.  Ma questa in definitiva è solo una
+complicazione inutile, il problema è che i semafori del \textit{SysV IPC}
+soffrono di altri due, ben più gravi, difetti.
+
+Il primo difetto è che non esiste una funzione che permetta di creare ed
+inizializzare un semaforo in un'unica chiamata; occorre prima creare l'insieme
+dei semafori con \func{semget} e poi inizializzarlo con \func{semctl}, si
+perde così ogni possibilità di eseguire l'operazione atomicamente.
+
+Il secondo difetto deriva dalla caratteristica generale degli oggetti del
+\textit{SysV IPC} di essere risorse globali di sistema, che non vengono
+cancellate quando nessuno le usa più; ci si così a trova a dover affrontare
+esplicitamente il caso in cui un processo termina per un qualche errore,
+lasciando un semaforo occupato, che resterà tale fino al successivo riavvio
+del sistema. Come vedremo esistono delle modalità per evitare tutto ciò, ma
+diventa necessario indicare esplicitamente che si vuole il ripristino del
+semaforo all'uscita del processo.
+
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct semid_ds
+{
+    struct ipc_perm sem_perm;           /* operation permission struct */
+    time_t sem_otime;                   /* last semop() time */
+    time_t sem_ctime;                   /* last time changed by semctl() */
+    unsigned long int sem_nsems;        /* number of semaphores in set */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{semid\_ds}, associata a ciascun insieme di
+    semafori.}
+  \label{fig:ipc_semid_ds}
+\end{figure}
+
+A ciascun insieme di semafori è associata una struttura \struct{semid\_ds},
+riportata in \figref{fig:ipc_semid_ds}.\footnote{non si sono riportati i campi
+  ad uso interno del kernel, che vedremo in \figref{fig:ipc_sem_schema}, che
+  dipendono dall'implementazione.} Come nel caso delle code di messaggi quando
+si crea un nuovo insieme di semafori con \func{semget} questa struttura viene
+inizializzata, in particolare il campo \var{sem\_perm} viene inizializzato
+come illustrato in \secref{sec:ipc_sysv_access_control} (si ricordi che in
+questo caso il permesso di scrittura è in realtà permesso di alterare il
+semaforo), per quanto riguarda gli altri campi invece:
+\begin{itemize*}
+\item il campo \var{sem\_nsems}, che esprime il numero di semafori
+  nell'insieme, viene inizializzato al valore di \param{nsems}.
+\item il campo \var{sem\_ctime}, che esprime il tempo di creazione
+  dell'insieme, viene inizializzato al tempo corrente.
+\item il campo \var{sem\_otime}, che esprime il tempo dell'ultima operazione
+  effettuata, viene inizializzato a zero.
+\end{itemize*}
+
+
+Ciascun semaforo dell'insieme è realizzato come una struttura di tipo
+\struct{sem} che ne contiene i dati essenziali, la sua definizione\footnote{si
+  è riportata la definizione originaria del kernel 1.0, che contiene la prima
+  realizzazione del \textit{SysV IPC} in Linux. In realtà questa struttura
+  ormai è ridotta ai soli due primi membri, e gli altri vengono calcolati
+  dinamicamente. La si è utilizzata a scopo di esempio, perché indica tutti i
+  valori associati ad un semaforo, restituiti dalle funzioni di controllo, e
+  citati dalle pagine di manuale.} è riportata in \figref{fig:ipc_sem}. Questa
+struttura, non è accessibile in user space, ma i valori in essa specificati
+possono essere letti in maniera indiretta, attraverso l'uso delle funzioni di
+controllo.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct sem {
+  short   sempid;         /* pid of last operation */
+  ushort  semval;         /* current value */
+  ushort  semncnt;        /* num procs awaiting increase in semval */
+  ushort  semzcnt;        /* num procs awaiting semval = 0 */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{sem}, che contiene i dati di un singolo
+    semaforo.} 
+  \label{fig:ipc_sem}
+\end{figure}
+
+I dati mantenuti nella struttura, ed elencati in \figref{fig:ipc_sem},
+indicano rispettivamente:
+\begin{description*}
+\item[\var{semval}] il valore numerico del semaforo.
+\item[\var{sempid}] il \acr{pid} dell'ultimo processo che ha eseguito una
+  operazione sul semaforo.
+\item[\var{semncnt}] il numero di processi in attesa che esso venga
+  incrementato.
+\item[\var{semzcnt}] il numero di processi in attesa che esso si annulli.
+\end{description*}
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|r|p{8cm}|}
+    \hline
+    \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{SEMMNI}&          128 & Numero massimo di insiemi di semafori. \\
+    \const{SEMMSL}&          250 & Numero massimo di semafori per insieme.\\
+    \const{SEMMNS}&\const{SEMMNI}*\const{SEMMSL}& Numero massimo di semafori
+                                   nel sistema .\\
+    \const{SEMVMX}&        32767 & Massimo valore per un semaforo.\\
+    \const{SEMOPM}&           32 & Massimo numero di operazioni per chiamata a
+                                   \func{semop}. \\
+    \const{SEMMNU}&\const{SEMMNS}& Massimo numero di strutture di ripristino.\\
+    \const{SEMUME}&\const{SEMOPM}& Massimo numero di voci di ripristino.\\
+    \const{SEMAEM}&\const{SEMVMX}& valore massimo per l'aggiustamento
+                                   all'uscita. \\
+    \hline
+  \end{tabular}
+  \caption{Valori delle costanti associate ai limiti degli insiemi di
+    semafori, definite in \file{linux/sem.h}.} 
+  \label{tab:ipc_sem_limits}
+\end{table}
+
+Come per le code di messaggi anche per gli insiemi di semafori esistono una
+serie di limiti, i cui valori sono associati ad altrettante costanti, che si
+sono riportate in \tabref{tab:ipc_sem_limits}. Alcuni di questi limiti sono al
+solito accessibili e modificabili attraverso \func{sysctl} o scrivendo
+direttamente nel file \file{/proc/sys/kernel/sem}.
+
+La funzione che permette di effettuare le varie operazioni di controllo sui
+semafori (fra le quali, come accennato, è impropriamente compresa anche la
+loro inizializzazione) è \funcd{semctl}; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/sem.h} 
+  
+  \funcdecl{int semctl(int semid, int semnum, int cmd)}
+  \funcdecl{int semctl(int semid, int semnum, int cmd, union semun arg)}
+  
+  Esegue le operazioni di controllo su un semaforo o un insieme di semafori.
+  
+  \bodydesc{La funzione restituisce in caso di successo un valore positivo
+    quanto usata con tre argomenti ed un valore nullo quando usata con
+    quattro. In caso di errore restituisce -1, ed \var{errno} assumerà uno dei
+    valori:
+    \begin{errlist}
+    \item[\errcode{EACCES}] Il processo non ha i privilegi per eseguire
+      l'operazione richiesta.
+    \item[\errcode{EIDRM}] L'insieme di semafori è stato cancellato.
+    \item[\errcode{EPERM}] Si è richiesto \const{IPC\_SET} o \const{IPC\_RMID}
+      ma il processo non ha privilegi sufficienti ad eseguire l'operazione.
+    \item[\errcode{ERANGE}] Si è richiesto \const{SETALL} \const{SETVAL} ma il
+      valore a cui si vuole impostare il semaforo è minore di zero o maggiore
+      di \const{SEMVMX}.
+  \end{errlist}
+  ed inoltre \errval{EFAULT} ed \errval{EINVAL}.
+}
 \end{functions}
 
-La funzione è del tutto analoga a \func{msgget} ed identico è l'uso degli
-argomenti \param{key} e \param{flag}, per cui non ripeteremo quanto detto al
-proposito in \secref{sec:ipc_sysv_mq}. L'argomento \param{nsems} permette di
-specificare quanti semafori deve contenere l'insieme qualora se ne richieda la
-creazione, e deve essere nullo quando si effettua una richiesta
-dell'identificatore di un insieme già esistente.
+La funzione può avere tre o quattro parametri, a seconda dell'operazione
+specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
+\param{semid} o sul singolo semaforo di un insieme, specificato da
+\param{semnum}. 
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+union semun {
+      int val;                  /* value for SETVAL */
+      struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
+      unsigned short *array;    /* array for GETALL, SETALL */
+                                /* Linux specific part: */
+      struct seminfo *__buf;    /* buffer for IPC_INFO */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La definizione dei possibili valori di una \direct{union}
+    \structd{semun}, usata come quarto argomento della funzione
+    \func{semctl}.}
+  \label{fig:ipc_semun}
+\end{figure}
+
+Qualora la funzione operi con quattro argomenti \param{arg} è un argomento
+generico, che conterrà un dato diverso a seconda dell'azione richiesta; per
+unificare l'argomento esso deve essere passato come una \struct{semun}, la cui
+definizione, con i possibili valori che può assumere, è riportata in
+\figref{fig:ipc_semun}.
+
+Come già accennato sia il comportamento della funzione che il numero di
+parametri con cui deve essere invocata, dipendono dal valore dell'argomento
+\param{cmd}, che specifica l'azione da intraprendere; i valori validi (che
+cioè non causano un errore di \errcode{EINVAL}) per questo argomento sono i
+seguenti:
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiando il
+  contenuto della relativa struttura \struct{semid\_ds} all'indirizzo
+  specificato con \var{arg.buf}. Occorre avere il permesso di lettura.
+  L'argomento \param{semnum} viene ignorato.
+\item[\const{IPC\_RMID}] Rimuove l'insieme di semafori e le relative strutture
+  dati, con effetto immediato. Tutti i processi che erano stato di
+  \textit{sleep} vengono svegliati, ritornando con un errore di
+  \errcode{EIDRM}.  L'user-ID effettivo del processo deve corrispondere o al
+  creatore o al proprietario dell'insieme, o all'amministratore. L'argomento
+  \param{semnum} viene ignorato.
+\item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+  dell'insieme. I valori devono essere passati in una struttura
+  \struct{semid\_ds} puntata da \param{arg.buf} di cui saranno usati soltanto i
+  campi \var{sem\_perm.uid}, \var{sem\_perm.gid} e i nove bit meno
+  significativi di \var{sem\_perm.mode}. L'user-ID effettivo del processo deve
+  corrispondere o al creatore o al proprietario dell'insieme, o
+  all'amministratore.  L'argomento \param{semnum} viene ignorato.
+\item[\const{GETALL}] Restituisce il valore corrente di ciascun semaforo
+  dell'insieme (corrispondente al campo \var{semval} di \struct{sem}) nel
+  vettore indicato da \param{arg.array}. Occorre avere il permesso di lettura.
+  L'argomento \param{semnum} viene ignorato.
+\item[\const{GETNCNT}] Restituisce come valore di ritorno della funzione il
+  numero di processi in attesa che il semaforo \param{semnum} dell'insieme
+  \param{semid} venga incrementato (corrispondente al campo \var{semncnt} di
+  \struct{sem}); va invocata con tre argomenti.  Occorre avere il permesso di
+  lettura.
+\item[\const{GETPID}] Restituisce come valore di ritorno della funzione il
+  \acr{pid} dell'ultimo processo che ha compiuto una operazione sul semaforo
+  \param{semnum} dell'insieme \param{semid} (corrispondente al campo
+  \var{sempid} di \struct{sem}); va invocata con tre argomenti.  Occorre avere
+  il permesso di lettura.
+\item[\const{GETVAL}] Restituisce come valore di ritorno della funzione il il
+  valore corrente del semaforo \param{semnum} dell'insieme \param{semid}
+  (corrispondente al campo \var{semval} di \struct{sem}); va invocata con tre
+  argomenti.  Occorre avere il permesso di lettura.
+\item[\const{GETZCNT}] Restituisce come valore di ritorno della funzione il
+  numero di processi in attesa che il valore del semaforo \param{semnum}
+  dell'insieme \param{semid} diventi nullo (corrispondente al campo
+  \var{semncnt} di \struct{sem}); va invocata con tre argomenti.  Occorre avere
+  il permesso di lettura.
+\item[\const{SETALL}] Inizializza il valore di tutti i semafori dell'insieme,
+  aggiornando il campo \var{sem\_ctime} di \struct{semid\_ds}. I valori devono
+  essere passati nel vettore indicato da \param{arg.array}.  Si devono avere i
+  privilegi di scrittura sul semaforo.  L'argomento \param{semnum} viene
+  ignorato.
+\item[\const{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato
+  dall'argomento \param{arg.val}, aggiornando il campo \var{sem\_ctime} di
+  \struct{semid\_ds}.  Si devono avere i privilegi di scrittura sul semaforo.
+\end{basedescript}
+
+Quando si imposta il valore di un semaforo (sia che lo si faccia per tutto
+l'insieme con \const{SETALL}, che per un solo semaforo con \const{SETVAL}), i
+processi in attesa su di esso reagiscono di conseguenza al cambiamento di
+valore.  Inoltre la coda delle operazioni di ripristino viene cancellata per
+tutti i semafori il cui valore viene modificato.
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|l|}
+    \hline
+    \textbf{Operazione}  & \textbf{Valore restituito} \\
+    \hline
+    \hline
+    \const{GETNCNT}& valore di \var{semncnt}.\\
+    \const{GETPID} & valore di \var{sempid}.\\
+    \const{GETVAL} & valore di \var{semval}.\\
+    \const{GETZCNT}& valore di \var{semzcnt}.\\
+    \hline
+  \end{tabular}
+  \caption{Valori di ritorno della funzione \func{semctl}.} 
+  \label{tab:ipc_semctl_returns}
+\end{table}
+
+Il valore di ritorno della funzione in caso di successo dipende
+dall'operazione richiesta; per tutte le operazioni che richiedono quattro
+argomenti esso è sempre nullo, per le altre operazioni, elencate in
+\tabref{tab:ipc_semctl_returns} viene invece restituito il valore richiesto,
+corrispondente al campo della struttura \struct{sem} indicato nella seconda
+colonna della tabella.
+
+Le operazioni ordinarie sui semafori, come l'acquisizione o il rilascio degli
+stessi (in sostanza tutte quelle non comprese nell'uso di \func{semctl})
+vengono effettuate con la funzione \funcd{semop}, il cui prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/sem.h} 
+  
+  \funcdecl{int semop(int semid, struct sembuf *sops, unsigned nsops)}
+  
+  Esegue le operazioni ordinarie su un semaforo o un insieme di semafori.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+    \begin{errlist}
+    \item[\errcode{EACCES}] Il processo non ha i privilegi per eseguire
+      l'operazione richiesta.
+    \item[\errcode{EIDRM}] L'insieme di semafori è stato cancellato.
+    \item[\errcode{ENOMEM}] Si è richiesto un \const{SEM\_UNDO} ma il sistema
+      non ha le risorse per allocare la struttura di ripristino.
+    \item[\errcode{EAGAIN}] Un'operazione comporterebbe il blocco del processo,
+      ma si è specificato \const{IPC\_NOWAIT} in \var{sem\_flg}.
+    \item[\errcode{EINTR}] La funzione, bloccata in attesa dell'esecuzione
+      dell'operazione, viene interrotta da un segnale.
+    \item[\errcode{E2BIG}] L'argomento \param{nsops} è maggiore del numero
+      massimo di operazioni \const{SEMOPM}.
+    \item[\errcode{ERANGE}] Per alcune operazioni il valore risultante del
+      semaforo viene a superare il limite massimo \const{SEMVMX}.
+  \end{errlist}
+  ed inoltre \errval{EFAULT} ed \errval{EINVAL}.
+}
+\end{functions}
+
+La funzione permette di eseguire operazioni multiple sui singoli semafori di
+un insieme. La funzione richiede come primo argomento l'identificatore
+\param{semid} dell'insieme su cui si vuole operare. Il numero di operazioni da
+effettuare viene specificato con l'argomento \param{nsop}, mentre il loro
+contenuto viene passato con un puntatore ad un vettore di strutture
+\struct{sembuf} nell'argomento \param{sops}. Le operazioni richieste vengono
+effettivamente eseguite se e soltanto se è possibile effettuarle tutte quante.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct sembuf
+{
+  unsigned short int sem_num;   /* semaphore number */
+  short int sem_op;             /* semaphore operation */
+  short int sem_flg;            /* operation flag */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{sembuf}, usata per le operazioni sui
+    semafori.}
+  \label{fig:ipc_sembuf}
+\end{figure}
+
+Il contenuto di ciascuna operazione deve essere specificato attraverso una
+opportuna struttura \struct{sembuf} (la cui definizione è riportata in
+\figref{fig:ipc_sembuf}) che il programma chiamante deve avere cura di
+allocare in un opportuno vettore. La struttura permette di indicare il
+semaforo su cui operare, il tipo di operazione, ed un flag di controllo.
+Il campo \var{sem\_num} serve per indicare a quale semaforo dell'insieme fa
+riferimento l'operazione; si ricordi che i semafori sono numerati come in un
+vettore, per cui il primo semaforo corrisponde ad un valore nullo di
+\var{sem\_num}.
+
+Il campo \var{sem\_flg} è un flag, mantenuto come maschera binaria, per il
+quale possono essere impostati i due valori \const{IPC\_NOWAIT} e
+\const{SEM\_UNDO}.  Impostando \const{IPC\_NOWAIT} si fa si che, invece di
+bloccarsi (in tutti quei casi in cui l'esecuzione di una operazione richiede
+che il processo vada in stato di \textit{sleep}), \func{semop} ritorni
+immediatamente con un errore di \errcode{EAGAIN}.  Impostando \const{SEM\_UNDO}
+si richiede invece che l'operazione venga registrata in modo che il valore del
+semaforo possa essere ripristinato all'uscita del processo.
+
+Infine \var{sem\_op} è il campo che controlla l'operazione che viene eseguita
+e determina il comportamento della chiamata a \func{semop}; tre sono i casi
+possibili:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\var{sem\_op}$>0$] In questo caso il valore di \var{sem\_op} viene
+  aggiunto al valore corrente di \var{semval}. La funzione ritorna
+  immediatamente (con un errore di \errcode{ERANGE} qualora si sia superato il
+  limite \const{SEMVMX}) ed il processo non viene bloccato in nessun caso.
+  Specificando \const{SEM\_UNDO} si aggiorna il contatore per il ripristino
+  del valore del semaforo. Al processo chiamante è richiesto il privilegio di
+  alterazione (scrittura) sull'insieme di semafori.
+  
+\item[\var{sem\_op}$=0$] Nel caso \var{semval} sia zero l'esecuzione procede
+  immediatamente. Se \var{semval} è diverso da zero il comportamento è
+  controllato da \var{sem\_flg}, se è stato impostato \const{IPC\_NOWAIT} la
+  funzione ritorna con un errore di \errcode{EAGAIN}, altrimenti viene
+  incrementato \var{semzcnt} di uno ed il processo resta in stato di
+  \textit{sleep} fintanto che non si ha una delle condizioni seguenti:
+  \begin{itemize*}
+  \item \var{semval} diventa zero, nel qual caso \var{semzcnt} viene
+    decrementato di uno.
+  \item l'insieme di semafori viene rimosso, nel qual caso \func{semop} ritorna
+    un errore di \errcode{EIDRM}.
+  \item il processo chiamante riceve un segnale, nel qual caso \var{semzcnt}
+    viene decrementato di uno e \func{semop} ritorna un errore di
+    \errcode{EINTR}.
+  \end{itemize*}
+  Al processo chiamante è richiesto il privilegio di lettura dell'insieme dei
+  semafori.
+  
+\item[\var{sem\_op}$<0$] Nel caso in cui \var{semval} è maggiore o uguale del
+  valore assoluto di \var{sem\_op} (se cioè la somma dei due valori resta
+  positiva o nulla) i valori vengono sommati e la funzione ritorna
+  immediatamente; qualora si sia impostato \const{SEM\_UNDO} viene anche
+  aggiornato il contatore per il ripristino del valore del semaforo. In caso
+  contrario (quando cioè la somma darebbe luogo ad un valore di \var{semval}
+  negativo) se si è impostato \const{IPC\_NOWAIT} la funzione ritorna con un
+  errore di \errcode{EAGAIN}, altrimenti viene incrementato di uno
+  \var{semncnt} ed il processo resta in stato di \textit{sleep} fintanto che
+  non si ha una delle condizioni seguenti:
+  \begin{itemize*}
+  \item \var{semval} diventa maggiore o uguale del valore assoluto di
+    \var{sem\_op}, nel qual caso \var{semncnt} viene decrementato di uno, il
+    valore di \var{sem\_op} viene sommato a \var{semval}, e se era stato
+    impostato \const{SEM\_UNDO} viene aggiornato il contatore per il
+    ripristino del valore del semaforo.
+  \item l'insieme di semafori viene rimosso, nel qual caso \func{semop}
+    ritorna un errore di \errcode{EIDRM}.
+  \item il processo chiamante riceve un segnale, nel qual caso \var{semncnt}
+    viene decrementato di uno e \func{semop} ritorna un errore di
+    \errcode{EINTR}.
+  \end{itemize*}    
+  Al processo chiamante è richiesto il privilegio di alterazione (scrittura)
+  sull'insieme di semafori.
+\end{basedescript}
+
+In caso di successo della funzione viene aggiornato il campo \var{sempid} per
+ogni semaforo modificato al valore del \acr{pid} del processo chiamante;
+inoltre vengono pure aggiornati al tempo corrente i campi \var{sem\_otime} e
+\var{sem\_ctime}.
+
+Dato che, come già accennato in precedenza, in caso di uscita inaspettata i
+semafori possono restare occupati, abbiamo visto come \func{semop} permetta di
+attivare un meccanismo di ripristino attraverso l'uso del flag
+\const{SEM\_UNDO}. Il meccanismo è implementato tramite una apposita struttura
+\struct{sem\_undo}, associata ad ogni processo per ciascun semaforo che esso
+ha modificato; all'uscita i semafori modificati vengono ripristinati, e le
+strutture disallocate.  Per mantenere coerente il comportamento queste
+strutture non vengono ereditate attraverso una \func{fork} (altrimenti si
+avrebbe un doppio ripristino), mentre passano inalterate nell'esecuzione di
+una \func{exec} (altrimenti non si avrebbe ripristino).
+
+Tutto questo però ha un problema di fondo. Per capire di cosa si tratta
+occorre fare riferimento all'implementazione usata in Linux, che è riportata
+in maniera semplificata nello schema di \figref{fig:ipc_sem_schema}.  Si è
+presa come riferimento l'architettura usata fino al kernel 2.2.x che è più
+semplice (ed illustrata in dettaglio in \cite{tlk}); nel kernel 2.4.x la
+struttura del \textit{SysV IPC} è stata modificata, ma le definizioni relative
+a queste strutture restano per compatibilità.\footnote{in particolare con le
+  vecchie versioni delle librerie del C, come le libc5.}
+
+\begin{figure}[htb]
+  \centering \includegraphics[width=15cm]{img/semtruct}
+  \caption{Schema della struttura di un insieme di semafori.}
+  \label{fig:ipc_sem_schema}
+\end{figure}
+
+Alla creazione di un nuovo insieme viene allocata una nuova strutture
+\struct{semid\_ds} ed il relativo vettore di strutture \struct{sem}. Quando si
+richiede una operazione viene anzitutto verificato che tutte le operazioni
+possono avere successo; se una di esse comporta il blocco del processo il
+kernel crea una struttura \struct{sem\_queue} che viene aggiunta in fondo alla
+coda di attesa associata a ciascun insieme di semafori\footnote{che viene
+  referenziata tramite i campi \var{sem\_pending} e \var{sem\_pending\_last}
+  di \struct{semid\_ds}.}. Nella struttura viene memorizzato il riferimento
+alle operazioni richieste (nel campo \var{sops}, che è un puntatore ad una
+struttura \struct{sembuf}) e al processo corrente (nel campo \var{sleeper}) poi
+quest'ultimo viene messo stato di attesa e viene invocato lo
+scheduler\index{scheduler} per passare all'esecuzione di un altro processo.
+
+Se invece tutte le operazioni possono avere successo queste vengono eseguite
+immediatamente, dopo di che il kernel esegue una scansione della coda di
+attesa (a partire da \var{sem\_pending}) per verificare se qualcuna delle
+operazioni sospese in precedenza può essere eseguita, nel qual caso la
+struttura \struct{sem\_queue} viene rimossa e lo stato del processo associato
+all'operazione (\var{sleeper}) viene riportato a \textit{running}; il tutto
+viene ripetuto fin quando non ci sono più operazioni eseguibili o si è
+svuotata la coda.
+
+Per gestire il meccanismo del ripristino tutte le volte che per un'operazione
+si è specificato il flag \const{SEM\_UNDO} viene mantenuta per ciascun insieme
+di semafori una apposita struttura \struct{sem\_undo} che contiene (nel vettore
+puntato dal campo \var{semadj}) un valore di aggiustamento per ogni semaforo
+cui viene sommato l'opposto del valore usato per l'operazione. 
+
+Queste strutture sono mantenute in due liste,\footnote{rispettivamente
+  attraverso i due campi \var{id\_next} e \var{proc\_next}.} una associata
+all'insieme di cui fa parte il semaforo, che viene usata per invalidare le
+strutture se questo viene cancellato o per azzerarle se si è eseguita una
+operazione con \func{semctl}; l'altra associata al processo che ha eseguito
+l'operazione;\footnote{attraverso il campo \var{semundo} di
+  \struct{task\_struct}, come mostrato in \ref{fig:ipc_sem_schema}.} quando un
+processo termina, la lista ad esso associata viene scandita e le operazioni
+applicate al semaforo.
+
+Siccome un processo può accumulare delle richieste di ripristino per semafori
+differenti chiamate attraverso diverse chiamate a \func{semop}, si pone il
+problema di come eseguire il ripristino dei semafori all'uscita del processo,
+ed in particolare se questo può essere fatto atomicamente. Il punto è cosa
+succede quando una delle operazioni previste per il ripristino non può essere
+eseguita immediatamente perché ad esempio il semaforo è occupato; in tal caso
+infatti, se si pone il processo in stato di \textit{sleep} aspettando la
+disponibilità del semaforo (come faceva l'implementazione originaria) si perde
+l'atomicità dell'operazione. La scelta fatta dal kernel è pertanto quella di
+effettuare subito le operazioni che non prevedono un blocco del processo e di
+ignorare silenziosamente le altre; questo però comporta il fatto che il
+ripristino non è comunque garantito in tutte le occasioni.
+
+Come esempio di uso dell'interfaccia dei semafori vediamo come implementare
+con essa dei semplici \textit{mutex} (cioè semafori binari), tutto il codice
+in questione, contenuto nel file \file{Mutex.c} allegato ai sorgenti, è
+riportato in \figref{fig:ipc_mutex_create}. Utilizzeremo l'interfaccia per
+creare un insieme contenente un singolo semaforo, per il quale poi useremo un
+valore unitario per segnalare la disponibilità della risorsa, ed un valore
+nullo per segnalarne l'indisponibilità. 
+
+\begin{figure}[!bht]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{} 
+/* Function MutexCreate: create a mutex/semaphore */
+int MutexCreate(key_t ipc_key) 
+{
+    const union semun semunion={1};             /* semaphore union structure */
+    int sem_id, ret;
+    sem_id = semget(ipc_key, 1, IPC_CREAT|0666);         /* get semaphore ID */
+    if (sem_id == -1) {                              /* if error return code */
+        return sem_id;
+    }
+    ret = semctl(sem_id, 0, SETVAL, semunion);             /* init semaphore */
+    if (ret == -1) {
+        return ret;
+    }
+    return sem_id;
+}
+/* Function MutexFind: get the semaphore/mutex Id given the IPC key value */
+int MutexFind(key_t ipc_key) 
+{
+    return semget(ipc_key,1,0);
+}
+/* Function MutexRead: read the current value of the mutex/semaphore */
+int MutexRead(int sem_id) 
+{
+    return semctl(sem_id, 0, GETVAL);
+}
+/* Define sembuf structures to lock and unlock the semaphore  */
+struct sembuf sem_lock={                                /* to lock semaphore */
+    0,                                   /* semaphore number (only one so 0) */
+    -1,                                    /* operation (-1 to use resource) */
+    SEM_UNDO};                                /* flag (set for undo at exit) */
+struct sembuf sem_ulock={                             /* to unlock semaphore */
+    0,                                   /* semaphore number (only one so 0) */
+    1,                                  /* operation (1 to release resource) */
+    SEM_UNDO};                                      /* flag (in this case 0) */
+/* Function MutexLock: to lock a mutex/semaphore */
+int MutexLock(int sem_id) 
+{
+    return semop(sem_id, &sem_lock, 1);
+}
+/* Function MutexUnlock: to unlock a mutex/semaphore */
+int MutexUnlock(int sem_id) 
+{
+    return semop(sem_id, &sem_ulock, 1);
+}
+/* Function MutexRemove: remove a mutex/semaphore */
+int MutexRemove(int sem_id) 
+{
+    return semctl(sem_id, 0, IPC_RMID);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni che permettono di creare o recuperare
+    l'identificatore di un semaforo da utilizzare come \textit{mutex}.}
+  \label{fig:ipc_mutex_create}
+\end{figure}
+
+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 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 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 4})
+ad 1 per significare che risorsa è libera. In caso di errore (\texttt{\small
+  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 17--20}) è \func{MutexFind}, che, data una
+chiave, restituisce l'identificatore del semaforo ad essa associato. La
+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 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 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 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 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_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}
 
-Il terzo oggetto introdotto dal \textit{System V IPC} è quello della memoria
-condivisa. La funzione che permette di ottenerne uno è \func{shmget} ed il suo
-prototipo è:
+Il terzo oggetto introdotto dal \textit{SysV IPC} è quello dei segmenti di
+memoria condivisa. La funzione che permette di ottenerne uno è \funcd{shmget},
+ed il suo prototipo è:
 \begin{functions}
   \headdecl{sys/types.h} 
   \headdecl{sys/ipc.h} 
@@ -1560,41 +2604,989 @@ prototipo 
   Restituisce l'identificatore di una memoria condivisa.
   
   \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
-    in caso di errore, nel qual caso \var{errno} viene settato agli stessi
-    valori visti per \func{msgget}.}
+    in caso di errore, nel qual caso \var{errno} assumerà i valori:
+    \begin{errlist}
+    \item[\errcode{ENOSPC}] Si è superato il limite (\const{SHMMNI}) sul numero
+      di segmenti di memoria nel sistema, o cercato di allocare un segmento le
+      cui dimensioni fanno superare il limite di sistema (\const{SHMALL}) per
+      la memoria ad essi riservata.
+    \item[\errcode{EINVAL}] Si è richiesta una dimensione per un nuovo segmento
+      maggiore di \const{SHMMAX} o minore di \const{SHMMIN}, o se il segmento
+      già esiste \param{size} è maggiore delle sue dimensioni.
+    \item[\errcode{ENOMEM}] Il sistema non ha abbastanza memoria per poter
+      contenere le strutture per un nuovo segmento di memoria condivisa.
+    \end{errlist}
+    ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST},
+    \errval{EIDRM}, con lo stesso significato che hanno per \func{msgget}.}
 \end{functions}
 
 La funzione, come \func{semget}, è del tutto analoga a \func{msgget}, ed
-identico è l'uso degli argomenti \param{key} e \param{flag}. L'argomento
+identico è l'uso degli argomenti \param{key} e \param{flag} per cui non
+ripeteremo quanto detto al proposito in \secref{sec:ipc_sysv_mq}. L'argomento
+\param{size} specifica invece la dimensione, in byte, del segmento, che viene
+comunque arrotondata al multiplo superiore di \const{PAGE\_SIZE}.
+
+La memoria condivisa è la forma più veloce di comunicazione fra due processi,
+in quanto permette agli stessi di vedere nel loro spazio di indirizzi una
+stessa sezione di memoria.  Pertanto non è necessaria nessuna operazione di
+copia per trasmettere i dati da un processo all'altro, in quanto ciascuno può
+accedervi direttamente con le normali operazioni di lettura e scrittura dei
+dati in memoria.
+
+Ovviamente tutto questo ha un prezzo, ed il problema fondamentale della
+memoria condivisa è la sincronizzazione degli accessi. È evidente infatti che
+se un processo deve scambiare dei dati con un altro, si deve essere sicuri che
+quest'ultimo non acceda al segmento di memoria condivisa prima che il primo
+non abbia completato le operazioni di scrittura, inoltre nel corso di una
+lettura si deve essere sicuri che i dati restano coerenti e non vengono
+sovrascritti da un accesso in scrittura sullo stesso segmento da parte di un
+altro processo. Per questo in genere la memoria condivisa viene sempre
+utilizzata in abbinamento ad un meccanismo di sincronizzazione, il che, di
+norma, significa insieme a dei semafori.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}
+struct shmid_ds {
+     struct    ipc_perm shm_perm;  /* operation perms */
+     int  shm_segsz;               /* size of segment (bytes) */
+     time_t    shm_atime;          /* last attach time */
+     time_t    shm_dtime;          /* last detach time */
+     time_t    shm_ctime;          /* last change time */
+     unsigned short shm_cpid;      /* pid of creator */
+     unsigned short shm_lpid;      /* pid of last operator */
+     short     shm_nattch;         /* no. of current attaches */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{shmid\_ds}, associata a ciascun segmento di
+    memoria condivisa.}
+  \label{fig:ipc_shmid_ds}
+\end{figure}
+
+A ciascun segmento di memoria condivisa è associata una struttura
+\struct{shmid\_ds}, riportata in \figref{fig:ipc_shmid_ds}.  Come nel caso
+delle code di messaggi quando si crea un nuovo segmento di memoria condivisa
+con \func{shmget} questa struttura viene inizializzata, in particolare il
+campo \var{shm\_perm} viene inizializzato come illustrato in
+\secref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte
+relativamente ai permessi di accesso; per quanto riguarda gli altri campi
+invece:
+\begin{itemize*}
+\item il campo \var{shm\_segsz}, che esprime la dimensione del segmento, viene
+  inizializzato al valore di \param{size}.
+\item il campo \var{shm\_ctime}, che esprime il tempo di creazione del
+  segmento, viene inizializzato al tempo corrente.
+\item i campi \var{shm\_atime} e \var{shm\_dtime}, che esprimono
+  rispettivamente il tempo dell'ultima volta che il segmento è stato
+  agganciato o sganciato da un processo, vengono inizializzati a zero.
+\item il campo \var{shm\_lpid}, che esprime il \acr{pid} del processo che ha
+  eseguito l'ultima operazione, viene inizializzato a zero.
+\item il campo \var{shm\_cpid}, che esprime il \acr{pid} del processo che ha
+  creato il segmento, viene inizializzato al \acr{pid} del processo chiamante.
+\item il campo \var{shm\_nattac}, che esprime il numero di processi agganciati
+  al segmento viene inizializzato a zero.
+\end{itemize*}
+
+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
+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. 
+
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|r|c|p{7cm}|}
+    \hline
+    \textbf{Costante} & \textbf{Valore} & \textbf{File in \texttt{proc}}
+    & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{SHMALL}& 0x200000&\file{shmall}& Numero massimo di pagine che 
+                                       possono essere usate per i segmenti di
+                                       memoria condivisa. \\
+    \const{SHMMAX}&0x2000000&\file{shmmax}& Dimensione massima di un segmento 
+                                            di memoria condivisa.\\
+    \const{SHMMNI}&     4096&\file{msgmni}& Numero massimo di segmenti di 
+                                            memoria condivisa presenti nel
+                                            kernel.\\ 
+    \const{SHMMIN}&        1& ---         & Dimensione minima di un segmento di
+                                            memoria condivisa. \\
+    \const{SHMLBA}&\const{PAGE\_SIZE}&--- & Limite inferiore per le dimensioni
+                                            minime di un segmento (deve essere
+                                            allineato alle dimensioni di una
+                                            pagina di memoria). \\
+    \const{SHMSEG}&   ---   &     ---     & Numero massimo di segmenti di
+                                            memoria condivisa 
+                                            per ciascun processo.\\
+
+
+    \hline
+  \end{tabular}
+  \caption{Valori delle costanti associate ai limiti dei segmenti di memoria
+    condivisa, insieme al relativo file in \file{/proc/sys/kernel/} ed al
+    valore preimpostato presente nel sistema.} 
+  \label{tab:ipc_shm_limits}
+\end{table}
+
+Al solito la funzione che permette di effettuare le operazioni di controllo su
+un segmento di memoria condivisa è \funcd{shmctl}; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/ipc.h} 
+  \headdecl{sys/shm.h}
+  
+  \funcdecl{int shmctl(int shmid, int cmd, struct shmid\_ds *buf)}
+  
+  Esegue le operazioni di controllo su un segmento di memoria condivisa.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} assumerà i valori:
+    \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{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.
+    \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:
+\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.
+\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.
+\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
+  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\_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 è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/shm.h}
+  
+  \funcdecl{void *shmat(int shmid, const void *shmaddr, int shmflg)}
+  Aggancia al processo un segmento di memoria condivisa.
+  
+  \bodydesc{La funzione restituisce l'indirizzo del segmento in caso di
+    successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà i
+    valori:
+    \begin{errlist}
+    \item[\errcode{EACCES}] Il processo non ha i privilegi per accedere al
+      segmento nella modalità richiesta.
+    \item[\errcode{EINVAL}] Si è specificato un identificatore invalido per
+      \param{shmid}, o un indirizzo non allineato sul confine di una pagina
+      per \param{shmaddr}.
+    \end{errlist}
+    ed inoltre \errval{ENOMEM}.}
+\end{functions}
+
+La funzione inserisce un segmento di memoria condivisa all'interno dello
+spazio di indirizzi del processo, in modo che questo possa accedervi
+direttamente, la situazione dopo l'esecuzione di \func{shmat} è illustrata in
+\figref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
+ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). In
+particolare l'indirizzo finale del segmento dati (quello impostato da
+\func{brk}, vedi \secref{sec:proc_mem_sbrk}) non viene influenzato. Si tenga
+presente infine che la funzione ha successo anche se il segmento è stato
+marcato per la cancellazione.
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[height=10cm]{img/sh_memory_layout}
+  \caption{Disposizione dei segmenti di memoria di un processo quando si è
+    agganciato un segmento di memoria condivisa.}
+  \label{fig:ipc_shmem_layout}
+\end{figure}
+
+L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{Lo standard
+  SVID prevede che l'argomento \param{shmaddr} sia di tipo \ctyp{char *}, così
+  come il valore di ritorno della funzione. In Linux è stato così con le
+  \acr{libc4} e le \acr{libc5}, con il passaggio alle \acr{glibc} il tipo di
+  \param{shmaddr} è divenuto un \ctyp{const void *} e quello del valore di
+  ritorno un \ctyp{void *}.} deve essere associato il segmento, se il valore
+specificato è \val{NULL} è il sistema a scegliere opportunamente un'area di
+memoria libera (questo è il modo più portabile e sicuro di usare la funzione).
+Altrimenti il kernel aggancia il segmento all'indirizzo specificato da
+\param{shmaddr}; questo però può avvenire solo se l'indirizzo coincide con il
+limite di una pagina, cioè se è un multiplo esatto del parametro di sistema
+\const{SHMLBA}, che in Linux è sempre uguale \const{PAGE\_SIZE}. 
+
+Si tenga presente però che quando si usa \val{NULL} come valore di
+\param{shmaddr}, l'indirizzo restituito da \func{shmat} può cambiare da
+processo a processo; pertanto se nell'area di memoria condivisa si salvano
+anche degli indirizzi, si deve avere cura di usare valori relativi (in genere
+riferiti all'indirizzo di partenza del segmento).
+
+L'argomento \param{shmflg} permette di cambiare il comportamento della
+funzione; esso va specificato come maschera binaria, i bit utilizzati sono
+solo due e sono identificati dalle costanti \const{SHM\_RND} e
+\const{SHM\_RDONLY}, che vanno combinate con un OR aritmetico.  Specificando
+\const{SHM\_RND} si evita che \func{shmat} ritorni un errore quando
+\param{shmaddr} non è allineato ai confini di una pagina. Si può quindi usare
+un valore qualunque per \param{shmaddr}, e il segmento verrà comunque
+agganciato, ma al più vicino multiplo di \const{SHMLBA} (il nome della
+costante sta infatti per \textit{rounded}, e serve per specificare un
+indirizzo come arrotondamento, in Linux è equivalente a \const{PAGE\_SIZE}).
+
+L'uso di \const{SHM\_RDONLY} permette di agganciare il segmento in sola
+lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal
+caso un tentativo di scrivere sul segmento comporterà una violazione di
+accesso con l'emissione di un segnale di \const{SIGSEGV}. Il comportamento
+usuale di \func{shmat} è quello di agganciare il segmento con l'accesso in
+lettura e scrittura (ed il processo deve aver questi permessi in
+\var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in
+sola scrittura.
+
+In caso di successo la funzione aggiorna anche i seguenti campi di
+\struct{shmid\_ds}:
+\begin{itemize*}
+\item il tempo \var{shm\_atime} dell'ultima operazione di aggancio viene
+  impostato al tempo corrente.
+\item il \acr{pid} \var{shm\_lpid} dell'ultimo processo che ha operato sul
+  segmento viene impostato a quello del processo corrente.
+\item il numero \var{shm\_nattch} di processi agganciati al segmento viene
+  aumentato di uno.
+\end{itemize*} 
+
+Come accennato in \secref{sec:proc_fork} un segmento di memoria condivisa
+agganciato ad un processo viene ereditato da un figlio attraverso una
+\func{fork}, dato che quest'ultimo riceve una copia dello spazio degli
+indirizzi del padre. Invece, dato che attraverso una \func{exec} viene
+eseguito un diverso programma con uno spazio di indirizzi completamente
+diverso, tutti i segmenti agganciati al processo originario vengono
+automaticamente sganciati. Lo stesso avviene all'uscita del processo
+attraverso una \func{exit}.
+
+Una volta che un segmento di memoria condivisa non serve più, si può
+sganciarlo esplicitamente dal processo usando l'altra funzione
+dell'interfaccia, \funcd{shmdt}, il cui prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h} 
+  \headdecl{sys/shm.h}
+
+  \funcdecl{int shmdt(const void *shmaddr)}
+  Sgancia dal processo un segmento di memoria condivisa.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
+    errore, la funzione fallisce solo quando non c'è un segmento agganciato
+    all'indirizzo \func{shmaddr}, con \var{errno} che assume il valore
+    \errval{EINVAL}.}
+\end{functions}
+
+La funzione sgancia dallo spazio degli indirizzi del processo un segmento di
+memoria condivisa; questo viene identificato con l'indirizzo \param{shmaddr}
+restituito dalla precedente chiamata a \func{shmat} con il quale era stato
+agganciato al processo.
+
+In caso di successo la funzione aggiorna anche i seguenti campi di
+\struct{shmid\_ds}:
+\begin{itemize*}
+\item il tempo \var{shm\_dtime} dell'ultima operazione di sganciamento viene
+  impostato al tempo corrente.
+\item il \acr{pid} \var{shm\_lpid} dell'ultimo processo che ha operato sul
+  segmento viene impostato a quello del processo corrente.
+\item il numero \var{shm\_nattch} di processi agganciati al segmento viene
+  decrementato di uno.
+\end{itemize*} 
+inoltre la regione di indirizzi usata per il segmento di memoria condivisa
+viene tolta dallo spazio di indirizzi del processo.
+
+Benché la memoria condivisa costituisca il meccanismo di intercomunicazione
+fra processi più veloce, essa non è sempre il più appropriato, dato che, come
+abbiamo visto, si avrà comunque la necessità di una sincronizzazione degli
+accessi.  Per questo motivo, quando la comunicazione fra processi è
+sequenziale, altri meccanismi come le pipe, le fifo o i socket, che non
+necessitano di sincronizzazione esplicita, sono da preferire. Essa diventa
+l'unico meccanismo possibile quando la comunicazione non è
+sequenziale\footnote{come accennato in \secref{sec:ipc_sysv_mq} per la
+  comunicazione non sequenziale si possono usare le code di messaggi,
+  attraverso l'uso del campo \var{mtype}, ma solo se quest'ultima può essere
+  effettuata in forma di messaggio.} o quando non può avvenire secondo una
+modalità predefinita.
+
+Un esempio classico di uso della memoria condivisa è quello del
+``\textit{monitor}'', in cui viene per scambiare informazioni fra un processo
+server, che vi scrive dei dati di interesse generale che ha ottenuto, e i
+processi client interessati agli stessi dati che così possono leggerli in
+maniera completamente asincrona.  Con questo schema di funzionamento da una
+parte si evita che ciascun processo client debba compiere l'operazione,
+potenzialmente onerosa, di ricavare e trattare i dati, e dall'altra si evita
+al processo server di dover gestire l'invio a tutti i client di tutti i dati
+(non potendo il server sapere quali di essi servono effettivamente al singolo
+client).
+
+Nel nostro caso implementeremo un ``\textsl{monitor}'' di una directory: un
+processo si incaricherà di tenere sotto controllo alcuni parametri relativi ad
+una directory (il numero dei file contenuti, la dimensione totale, quante
+directory, link simbolici, file normali, ecc.) che saranno salvati in un
+segmento di memoria condivisa cui altri processi potranno accedere per
+ricavare la parte di informazione che interessa.
+
+In \figref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del
+corpo del programma server, insieme alle definizioni delle altre funzioni
+usate nel programma e delle variabili globali, omettendo tutto quello che
+riguarda la gestione delle opzioni e la stampa delle istruzioni di uso a
+video; al solito il codice completo si trova con i sorgenti allegati nel file
+\file{DirMonitor.c}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{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;    
+    int tot_files;   
+    int tot_regular; 
+    int tot_fifo;    
+    int tot_link;    
+    int tot_dir;     
+    int tot_block;   
+    int tot_char;    
+    int tot_sock;
+};
+struct DirProp *shmptr;
+int shmid; 
+int mutex;
+/* main body */
+int main(int argc, char *argv[]) 
+{
+    int i;
+    key_t key;
+    ...
+    if ((argc - optind) != 1) {          /* There must be remaing parameters */
+        printf("Wrong number of arguments %d\n", argc - optind);
+        usage();
+    }
+    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 */
+    shmid = shmget(key, 4096, IPC_CREAT|0666);        /* get a shared memory */
+    if (shmid < 0) {
+        perror("Cannot create shared memory");
+        exit(1);
+    }
+    if ( (shmptr = shmat(shmid, NULL, 0)) == NULL ) {   /* attach to process */
+        perror("Cannot attach segment");
+    }
+    if ((mutex = MutexCreate(key)) == -1) {                   /* get a Mutex */
+        perror("Cannot create mutex");
+        exit(1);
+    }
+    /* main loop, monitor directory properties each 10 sec */
+    while (1) {
+        MutexLock(mutex);                              /* lock shared memory */
+        memset(shmptr, 0, sizeof(struct DirProp));    /* erase previous data */
+        DirScan(argv[1], ComputeValues);                     /* execute scan */
+        MutexUnlock(mutex);                          /* unlock shared memory */
+        sleep(pause);                              /* sleep until next watch */
+    }
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice della funzione principale del programma \file{DirMonitor.c}.}
+  \label{fig:ipc_dirmonitor_main}
+\end{figure}
+
+Il programma usa delle variabili globali (\texttt{\small 4--18}) per mantenere
+i valori relativi agli oggetti usati per la comunicazione inter-processo; si è
+definita inoltre una apposita struttura \struct{DirProp} che contiene i dati
+relativi alle proprietà che si vogliono mantenere nella memoria condivisa, per
+l'accesso da parte dei client.
+
+Il programma, dopo la sezione, omessa, relativa alla gestione delle opzioni da
+riga di comando, che si limitano alla eventuale stampa di un messaggio di
+aiuto a video ed all'impostazione della durata dell'intervallo con cui viene
+ripetuto il calcolo delle proprietà della directory, controlla (\texttt{\small
+  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.
+
+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}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{} 
+...
+/*
+ * Routine  to compute directory properties inside DirScan
+ */
+int ComputeValues(struct dirent * direntry) 
+{
+    struct stat data;
+    stat(direntry->d_name, &data);                          /* get stat data */
+    shmptr->tot_size += data.st_size;
+    shmptr->tot_files++;
+    if (S_ISREG(data.st_mode)) shmptr->tot_regular++;
+    if (S_ISFIFO(data.st_mode)) shmptr->tot_fifo++;
+    if (S_ISLNK(data.st_mode)) shmptr->tot_link++;
+    if (S_ISDIR(data.st_mode)) shmptr->tot_dir;
+    if (S_ISBLK(data.st_mode)) shmptr->tot_block;
+    if (S_ISCHR(data.st_mode)) shmptr->tot_char;
+    if (S_ISSOCK(data.st_mode)) shmptr->tot_sock;
+    return 0;
+}
+/*
+ * Signal Handler to manage termination
+ */
+void HandSIGTERM(int signo) {
+    MutexLock(mutex);
+    if (shmdt(shmptr)) {
+        perror("Error detaching shared memory");
+        exit(1);
+    }
+    if (shmctl(shmid, IPC_RMID, NULL)) {
+        perror("Cannot remove shared memory segment");
+        exit(1);
+    }
+    MutexRemove(mutex);
+    exit(0);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice delle funzione ausiliarie usate da \file{DirMonitor.c}.}
+  \label{fig:ipc_dirmonitor_sub}
+\end{figure}
+
+Si noti come per il calcolo dei valori da mantenere nella memoria condivisa si
+sia usata ancora una volta la funzione \func{DirScan}, già utilizzata (e
+descritta in dettaglio) in \secref{sec:file_dir_read}, che ci permette di
+effettuare la scansione delle voci della directory, chiamando per ciascuna di
+esse la funzione \func{ComputeValues}, che esegue tutti i calcoli necessari.
+
+Il codice di quest'ultima è riportato in \figref{fig:ipc_dirmonitor_sub}. Come
+si vede la funzione (\texttt{\small 5--19}) è molto semplice e si limita a
+chiamare (\texttt{\small 8}) la funzione \func{stat} sul file indicato da
+ciascuna voce, per ottenerne i dati, che poi utilizza per incrementare i vari
+contatori.
+
+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
+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}.
+
+\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 */
+    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("File presenti %d file, per un totale di %d byte\n",
+           shmptr->tot_files, shmptr->tot_size);
+    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);
+    MutexUnlock(mutex);                              /* unlock shared memory */
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Codice del programma client \file{ReadMonitor.c}.}
+  \label{fig:ipc_dirmonitor_client}
+\end{figure}
+
+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.
+
+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. 
+
+
+%% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
+%% riferimento alle strutture con cui il kernel implementa i segmenti di memoria
+%% condivisa; uno schema semplificato della struttura è illustrato in
+%% \figref{fig:ipc_shm_struct}. 
+
+%% \begin{figure}[htb]
+%%   \centering
+%%   \includegraphics[width=10cm]{img/shmstruct}
+%%    \caption{Schema dell'implementazione dei segmenti di memoria condivisa in
+%%     Linux.}
+%%   \label{fig:ipc_shm_struct}
+%% \end{figure}
+
+
+
+
+\section{Tecniche alternative}
+\label{sec:ipc_alternatives}
+
+Come abbiamo detto in \secref{sec:ipc_sysv_generic}, e ripreso nella
+descrizione dei singoli oggetti che ne fan parte, il \textit{SysV IPC}
+presenta numerosi problemi; in \cite{APUE}\footnote{in particolare nel
+  capitolo 14.}  Stevens ne effettua una accurata analisi (alcuni dei concetti
+sono già stati accennati in precedenza) ed elenca alcune possibili tecniche
+alternative, che vogliamo riprendere in questa sezione.
+
+
+\subsection{Alternative alle code di messaggi}
+\label{sec:ipc_mq_alternative}
+Le code di messaggi sono probabilmente il meno usato degli oggetti del
+\textit{SysV IPC}; esse infatti nacquero principalmente come meccanismo di
+comunicazione bidirezionale quando ancora le pipe erano unidirezionali; con la
+disponibilità di \func{socketpair} (vedi \secref{sec:ipc_socketpair}) o
+utilizzando una coppia di pipe, si può ottenere questo risultato senza
+incorrere nelle complicazioni introdotte dal \textit{SysV IPC}.
+
+In realtà, grazie alla presenza del campo \var{mtype}, le code di messaggi
+hanno delle caratteristiche ulteriori, consentendo una classificazione dei
+messaggi ed un accesso non rigidamente sequenziale; due caratteristiche che
+sono impossibili da ottenere con le pipe e i socket\index{socket} di
+\func{socketpair}.  A queste esigenze però si può comunque ovviare in maniera
+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}
+
+\index{file!di lock|(}
+Come illustrato in \secref{sec:ipc_sysv_sem} i semafori del \textit{SysV IPC}
+presentano una interfaccia inutilmente complessa e con alcuni difetti
+strutturali, per questo quando si ha una semplice esigenza di sincronizzazione
+per la quale basterebbe un semaforo binario (quello che abbiamo definito come
+\textit{mutex}), per indicare la disponibilità o meno di una risorsa, senza la
+necessità di un contatore come i semafori, si possono utilizzare metodi
+alternativi.
+
+La prima possibilità, utilizzata fin dalle origini di Unix, è quella di usare
+dei \textsl{file di lock} (per i quali esiste anche una opportuna directory,
+\file{/var/lock}, nel filesystem standard). Per questo si usa la
+caratteristica della funzione \func{open} (illustrata in
+\secref{sec:file_open}) che prevede\footnote{questo è quanto dettato dallo
+  standard POSIX.1, ciò non toglie che in alcune implementazioni questa
+  tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si
+  è comunque soggetti alla possibilità di una race   
+  condition\index{race condition}.} che essa ritorni un errore quando usata
+con i flag di \const{O\_CREAT} e \const{O\_EXCL}. In tal modo la creazione di
+un \textsl{file di lock} può essere eseguita atomicamente, il processo che
+crea il file con successo si può considerare come titolare del lock (e della
+risorsa ad esso associata) mentre il rilascio si può eseguire con una chiamata
+ad \func{unlink}.
+
+Un esempio dell'uso di questa funzione è mostrato dalle funzioni
+\func{LockFile} ed \func{UnlockFile} riportate in \figref{fig:ipc_file_lock}
+(sono contenute in \file{LockFile.c}, un'altro dei sorgenti allegati alla
+guida) che permettono rispettivamente di creare e rimuovere un \textsl{file di
+  lock}. Come si può notare entrambe le funzioni sono elementari; la prima
+(\texttt{\small 4--10}) si limita ad aprire il file di lock (\texttt{\small
+  9}) nella modalità descritta, mentre la seconda (\texttt{\small 11--17}) lo
+cancella con \func{unlink}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{} 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>                               /* unix standard functions */
+/*
+ * Function LockFile:
+ */
+int LockFile(const char* path_name)
+{
+    return open(path_name, O_EXCL|O_CREAT);
+}
+/*
+ * Function UnlockFile:
+ */
+int UnlockFile(const char* path_name) 
+{
+    return unlink(path_name);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni \func{LockFile} e \func{UnlockFile} che
+    permettono di creare e rimuovere un \textsl{file di lock}.}
+  \label{fig:ipc_file_lock}
+\end{figure}
+
+Uno dei limiti di questa tecnica è che, come abbiamo già accennato in
+\secref{sec:file_open}, questo comportamento di \func{open} può non funzionare
+(la funzione viene eseguita, ma non è garantita l'atomicità dell'operazione)
+se il filesystem su cui si va ad operare è su NFS; in tal caso si può adottare
+una tecnica alternativa che prevede l'uso della \func{link} per creare come
+\textsl{file di lock} un hard link ad un file esistente; se il link esiste già
+e la funzione fallisce, significa che la risorsa è bloccata e potrà essere
+sbloccata solo con un \func{unlink}, altrimenti il link è creato ed il lock
+acquisito; il controllo e l'eventuale acquisizione sono atomici; la soluzione
+funziona anche su NFS, ma ha un'altro difetto è che è quello di poterla usare
+solo se si opera all'interno di uno stesso filesystem.
+
+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 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 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
+più programmi: qualora si trovi un file di lock il programma che cerca di
+accedere alla seriale si limita a segnalare che la risorsa non è
+disponibile.\index{file!di lock|)}
+
+
+\subsection{La sincronizzazione con il \textit{file locking}}
+\label{sec:ipc_lock_file}
+
+Dato che i file di lock\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
+leggermente più lento.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{} 
+/* Function CreateMutex: Create a mutex using file locking. */
+int CreateMutex(const char *path_name)
+{
+    return open(path_name, O_EXCL|O_CREAT);
+}
+/* Function UnlockMutex: unlock a file. */
+int FindMutex(const char *path_name)
+{
+    return open(path_name, O_RDWR);
+}
+/* Function LockMutex: lock mutex using file locking. */
+int LockMutex(int fd)
+{
+    struct flock lock;                                /* file lock structure */
+    /* 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 */
+    lock.l_start = 0;                  /* set the start of the locked region */
+    lock.l_len = 0;                   /* set the length of the locked region */
+    /* do locking */
+    return fcntl(fd, F_SETLKW, &lock);
+}
+/* Function UnlockMutex: unlock a file. */
+int UnlockMutex(int fd)
+{
+    struct flock lock;                                /* file lock structure */
+    /* set flock structure */
+    lock.l_type = F_UNLCK;                               /* set type: unlock */
+    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
+    lock.l_start = 0;                  /* set the start of the locked region */
+    lock.l_len = 0;                   /* set the length of the locked region */
+    /* do locking */
+    return fcntl(fd, F_SETLK, &lock);
+}
+/* Function RemoveMutex: remove a mutex (unlinking the lock file). */
+int RemoveMutex(const char *path_name)
+{
+    return unlink(path_name);
+}
+/* Function ReadMutex: read a mutex status. */
+int ReadMutex(int fd)
+{
+    int res;
+    struct flock lock;                                /* file lock structure */
+    /* set flock structure */
+    lock.l_type = F_WRLCK;                               /* set type: unlock */
+    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
+    lock.l_start = 0;                  /* set the start of the locked region */
+    lock.l_len = 0;                   /* set the length of the locked region */
+    /* do locking */
+    if ( (res = fcntl(fd, F_GETLK, &lock)) ) {
+        return res;
+    }
+    return lock.l_type;
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \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 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, 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, si è definita solo per mantenere una analogia con l'analoga
+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} per poter acquisire un write
+lock sul file, che poi (\texttt{\small 21}) viene richiesto con \func{fcntl}
+(restituendo il codice di ritorno). 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 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}.
+
+La quinta funzione \texttt{\small 36--40}) è \func{RemoveMutex} e serve a
+cancellare il mutex. Anche questa funzione è 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 saranno aperti.
+
+Basandosi sulla semantica dei file lock POSIX valgono tutte le precisazioni
+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.
+
+
+\subsection{Il \textit{memory mapping} anonimo}
+\label{sec:ipc_mmap_anonymous}
+
+Abbiamo già visto che quando i processi sono \textsl{correlati}\footnote{se
+  cioè hanno almeno un progenitore comune.} l'uso delle pipe può costituire
+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
+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
+tecnica per creare una memoria condivisa fra processi diversi è estremamente
+inefficiente, in quanto occorre passare attraverso il disco. Però abbiamo
+visto anche che se si esegue la mappatura con il flag \const{MAP\_ANONYMOUS}
+la regione mappata non viene associata a nessun file, anche se quanto scritto
+rimane in memoria e può essere riletto; allora, dato che un processo figlio
+mantiene nel suo spazio degli indirizzi anche le regioni mappate, esso sarà
+anche in grado di accedere a quanto in esse è contenuto.
+
+In questo modo diventa possibile creare una memoria condivisa fra processi
+diversi, purché questi abbiano almeno un progenitore comune che ha effettuato
+il \textit{memory mapping} anonimo.\footnote{nei sistemi derivati da SysV una
+  funzionalità simile a questa viene implementata mappando il file speciale
+  \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 
 
 
 
 \section{La comunicazione fra processi di POSIX}
 \label{sec:ipc_posix}
 
-Lo standard POSIX.1b ha introdotto dei nuovi meccanismi di comunicazione,
-rifacendosi a quelli di System V, introducendo una nuova interfaccia che
-evitasse i principali problemi evidenziati in coda a
-\secref{sec:ipc_sysv_generic}.  
+Per superare i numerosi problemi del \textit{SysV IPC}, evidenziati per i suoi
+aspetti generali in coda a \secref{sec:ipc_sysv_generic} e per i singoli
+oggetti nei paragrafi successivi, lo standard POSIX.1b ha introdotto dei nuovi
+meccanismi di comunicazione, che vanno sotto il nome di POSIX IPC, definendo
+una interfaccia completamente nuova, che tratteremo in questa sezione.
 
 
 
 \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}.
 
 
 \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.
+
+
 
 \subsection{Semafori}
 \label{sec:ipc_posix_sem}
 
+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. 
+
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_posix_shm}
 
+La memoria condivisa è l'unico degli oggetti di IPC POSIX già presente nel
+kernel ufficiale. 
+
+
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"