Correzioni varie
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index e56386f04109b2b17f287e121acbc3cafca9fb72..28481828c52cc9603a8804b0659b26e0206552d2 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}
 
@@ -46,8 +56,8 @@ associati ad una \textit{pipe} 
 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 dal parametro di sistema \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
+processo riceverà il segnale \errcode{EPIPE}, e la funzione di scrittura
+restituirà un errore di \errcode{EPIPE} (al ritorno del manipolatore, 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
@@ -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
@@ -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
@@ -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
@@ -508,7 +518,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.}
@@ -526,7 +536,7 @@ 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
@@ -683,7 +693,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
@@ -782,7 +792,7 @@ Inoltrata la richiesta si pu
 si apre (\texttt{\small 26--30}) la fifo appena creata, da cui si deve
 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.
@@ -796,7 +806,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
@@ -842,12 +852,12 @@ entrambe le direzioni. Il prototipo della funzione 
   \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[\macro{EAFNOSUPPORT}] I socket locali non sono supportati.
-  \item[\macro{EPROTONOSUPPORT}] Il protocollo specificato non è supportato.
-  \item[\macro{EOPNOTSUPP}] Il protocollo specificato non supporta la
+  \item[\errcode{EAFNOSUPPORT}] I 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.
   \end{errlist}
-  ed inoltre \macro{EMFILE},  \macro{EFAULT}.
+  ed inoltre \errval{EMFILE},  \errval{EFAULT}.
 }
 \end{functions}
 
@@ -857,7 +867,7 @@ sull'altro e viceversa. I parametri \param{domain}, \param{type} e
 \param{protocol} derivano dall'interfaccia dei 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
-\macro{AF\_UNIX}, \macro{SOCK\_STREAM} e \macro{0}.
+\const{AF\_UNIX}, \const{SOCK\_STREAM} e \var{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
@@ -879,20 +889,20 @@ 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
@@ -903,13 +913,13 @@ 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.
 
-Un'ulteriore caratteristica negativa è che 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
+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
@@ -922,7 +932,7 @@ 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 nell'IPC di System V.} Oltre la chiave, la
+  complicazioni inutili presenti nel \textit{SysV IPC}.} Oltre la chiave, la
 struttura, la cui definizione è riportata in \figref{fig:ipc_ipc_perm},
 mantiene varie proprietà ed informazioni associate all'oggetto.
 
@@ -973,7 +983,7 @@ file ed un numero di versione; il suo prototipo 
   
   \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} sarà uno dei possibili codici di
@@ -1011,11 +1021,11 @@ 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}
@@ -1036,8 +1046,8 @@ 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
@@ -1114,12 +1124,12 @@ assumere tutti i valori possibili, rendendo molto pi
 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 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
+  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 \texttt{syscntl}.} 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
@@ -1128,7 +1138,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.
@@ -1217,7 +1227,7 @@ 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 è:
@@ -1233,18 +1243,18 @@ una 
   \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
     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 superato il limite massimo di code (\macro{MSGMNI}).
+  \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}
 
@@ -1252,33 +1262,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]
@@ -1290,11 +1301,11 @@ 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 del contenuto di 
+    \const{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di 
                                           una coda.\\
     \hline
   \end{tabular}
@@ -1389,9 +1400,9 @@ gli altri campi invece:
   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 (\macro{MSGMNB}).
+  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 \macro{NULL} e
+  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).
@@ -1413,15 +1424,15 @@ prototipo 
   \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
     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 è stata 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}
 
@@ -1431,24 +1442,24 @@ 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{2.2cm}\desclabelstyle{\nextlinelabel}}
-\item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
+\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 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
   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}, ma l'amministratore ha la facoltà di
-  incrementarne il valore a limiti superiori a \macro{MSGMNB}.
+  incrementarne il valore a limiti superiori a \const{MSGMNB}.
 \end{basedescript}
 
 
@@ -1468,17 +1479,17 @@ messaggio su una coda si utilizza la funzione \func{msgsnd}; il suo prototipo
   \bodydesc{La funzione restituisce 0, 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{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}
 
@@ -1488,7 +1499,7 @@ l'argomento \param{msgp}.  Quest'ultimo deve venire passato sempre come
 puntatore ad una struttura \var{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 \macro{MSGMAX}.
+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
@@ -1511,7 +1522,7 @@ argomento 
 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 \macro{LENGTH}).
+dovrà essere pari a \const{LENGTH}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1544,16 +1555,16 @@ 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
@@ -1581,16 +1592,16 @@ La funzione che viene utilizzata per estrarre un messaggio da una coda 
     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}
 
@@ -1598,14 +1609,14 @@ 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 \macro{LENGTH} nell'esempio di
+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
-\macro{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene
+\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 \macro{E2BIG}.
+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
@@ -1626,20 +1637,20 @@ coda, 
 
 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 \macro{MSG\_NOERROR}, sono possibili altri due
-valori: \macro{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo,
+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
-\macro{IPC\_NOWAIT} che causa il ritorno immediato della funzione quando non
+\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 \macro{IPC\_NOWAIT} la
-funzione ritorna immediatamente con un errore \macro{ENOMSG}. Altrimenti la
+\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 \macro{EIDRM}) o se il processo viene interrotto da un
-segnale (con \var{errno} impostata a \macro{EINTR}).
+\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 \var{msqid\_ds}, in particolare vengono
@@ -1651,6 +1662,24 @@ modificati:
 \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
@@ -1753,7 +1782,7 @@ 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 \macro{MSG\_NOERROR}
+\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).
 
@@ -1886,7 +1915,7 @@ della risorsa; in generale per
 utilizzando il valore del contatore come indicatore del ``numero di risorse''
 ancora disponibili.
 
-Il sistema di comunicazione interprocesso di System V IPC prevede anche i
+Il sistema di comunicazione interprocesso 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 è
@@ -1903,19 +1932,19 @@ permette di creare o ottenere 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} assumerà i valori:
     \begin{errlist}
-    \item[\macro{ENOSPC}] Si è cercato di creare una insieme di semafori
+    \item[\errcode{ENOSPC}] Si è cercato di creare una insieme di semafori
       quando è stato superato o il limite per il numero totale di semafori
-      (\macro{SEMMNS}) o quello per il numero totale degli insiemi
-      (\macro{SEMMNI}) nel sistema.
-    \item[\macro{EINVAL}] L'argomento \param{nsems} è minore di zero o
+      (\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
-      (\macro{SEMMSL}), o se l'insieme già esiste, maggiore del numero di
+      (\const{SEMMSL}), o se l'insieme già esiste, maggiore del numero di
       semafori che contiene.
-    \item[\macro{ENOMEM}] Il sistema non ha abbastanza memoria per poter
+    \item[\errcode{ENOMEM}] Il sistema non ha abbastanza memoria per poter
       contenere le strutture per un nuovo insieme di semafori.
     \end{errlist}
-    ed inoltre \macro{EACCES}, \macro{ENOENT}, \macro{EEXIST}, \macro{EIDRM},
-    con lo stesso significato che hanno per \func{msgget}.}
+    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
@@ -1929,17 +1958,17 @@ richiesta dell'identificatore di un insieme gi
 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 System V IPC soffrono
-di altri due, ben più gravi, difetti.
+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 atomicamente questa operazione.
+perde così ogni possibilità di eseguire l'operazione atomicamente.
 
 Il secondo difetto deriva dalla caratteristica generale degli oggetti del
-System V IPC di essere risorse globali di sistema, che non vengono cancellate
-quando nessuno le usa più; ci si così a trova a dover affrontare
+\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
@@ -1988,8 +2017,8 @@ semaforo), per quanto riguarda gli altri campi invece:
 Ciascun semaforo dell'insieme è realizzato come una struttura di tipo
 \var{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 System V IPC in Linux. In realtà questa struttura ormai è
-  ridotta ai soli due primi membri, e gli altri vengono calcolati
+  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
@@ -2033,16 +2062,16 @@ indicano rispettivamente:
     \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \macro{SEMMNI}&          128 & Numero massimo di insiemi di semafori. \\
-    \macro{SEMMSL}&          250 & Numero massimo di semafori per insieme.\\
-    \macro{SEMMNS}&\macro{SEMMNI}*\macro{SEMMSL}& Numero massimo di semafori
+    \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 .\\
-    \macro{SEMVMX}&        32767 & Massimo valore per un semaforo.\\
-    \macro{SEMOPM}&           32 & Massimo numero di operazioni per chiamata a
+    \const{SEMVMX}&        32767 & Massimo valore per un semaforo.\\
+    \const{SEMOPM}&           32 & Massimo numero di operazioni per chiamata a
                                    \func{semop}. \\
-    \macro{SEMMNU}&\macro{SEMMNS}& Massimo numero di strutture di ripristino.\\
-    \macro{SEMUME}&\macro{SEMOPM}& Massimo numero di voci di ripristino.\\
-    \macro{SEMAEM}&\macro{SEMVMX}& valore massimo per l'aggiustamento
+    \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}
@@ -2075,16 +2104,16 @@ loro inizializzazione) 
     quattro. In caso di errore restituisce -1, ed \var{errno} assumerà uno dei
     valori:
     \begin{errlist}
-    \item[\macro{EACCES}] Il processo non ha i privilegi per eseguire
+    \item[\errcode{EACCES}] Il processo non ha i privilegi per eseguire
       l'operazione richiesta.
-    \item[\macro{EIDRM}] L'insieme di semafori è stato cancellato.
-    \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
-      il processo non ha  privilegi sufficienti ad eseguire l'operazione.
-    \item[\macro{ERANGE}] Si è richiesto \macro{SETALL} \macro{SETVAL} ma il
+    \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 \macro{SEMVMX}.
+      di \const{SEMVMX}.
   \end{errlist}
-  ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+  ed inoltre \errval{EFAULT} ed \errval{EINVAL}.
 }
 \end{functions}
 
@@ -2093,12 +2122,6 @@ 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}. 
 
-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
-\var{union semun}, la cui definizione, con i possibili valori che può
-assumere, è riportata in \figref{fig:ipc_semun}.
-
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
@@ -2118,64 +2141,70 @@ union semun {
   \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
+\var{union 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 \macro{EINVAL}) per questo argomento sono i
+cioè non causano un errore di \errcode{EINVAL}) per questo argomento sono i
 seguenti:
 \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
-\item[\macro{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiando il
+\item[\const{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiando il
   contenuto della relativa struttura \var{semid\_ds} all'indirizzo specificato
   con \var{arg.buf}. Occorre avere il permesso di lettura. L'argomento
   \param{semnum} viene ignorato.
-\item[\macro{IPC\_RMID}] Rimuove l'insieme di semafori e le relative strutture
+\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 \macro{EIDRM}.
-  L'userid effettivo del processo deve corrispondere o al creatore o al
-  proprietario dell'insieme, o all'amministratore. L'argomento \param{semnum}
-  viene ignorato.
-\item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+  \textit{sleep} vengono svegliati, ritornando con un errore di
+  \errcode{EIDRM}.  L'userid 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
   \var{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'userid effettivo del processo deve
   corrispondere o al creatore o al proprietario dell'insieme, o
   all'amministratore.  L'argomento \param{semnum} viene ignorato.
-\item[\macro{GETALL}] Restituisce il valore corrente di ciascun semaforo
+\item[\const{GETALL}] Restituisce il valore corrente di ciascun semaforo
   dell'insieme (corrispondente al campo \var{semval} di \var{sem}) nel vettore
   indicato da \param{arg.array}. Occorre avere il permesso di lettura.
   L'argomento \param{semnum} viene ignorato.
-\item[\macro{GETNCNT}] Restituisce come valore di ritorno della funzione il
+\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
   \var{sem}); va invocata con tre argomenti.  Occorre avere il permesso di
   lettura.
-\item[\macro{GETPID}] Restituisce come valore di ritorno della funzione il
+\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 \var{sem}); va invocata con tre argomenti.  Occorre avere il
   permesso di lettura.
-\item[\macro{GETVAL}] Restituisce come valore di ritorno della funzione il il
+\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 \var{sem}); va invocata con tre
   argomenti.  Occorre avere il permesso di lettura.
-\item[\macro{GETZCNT}] Restituisce come valore di ritorno della funzione il
+\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 \var{sem}); va invocata con tre argomenti.  Occorre avere
   il permesso di lettura.
-\item[\macro{SETALL}] Inizializza il valore di tutti i semafori dell'insieme,
+\item[\const{SETALL}] Inizializza il valore di tutti i semafori dell'insieme,
   aggiornando il campo \var{sem\_ctime} di \var{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[\macro{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato
+\item[\const{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato
   dall'argomento \param{arg.val}, aggiornando il campo \var{sem\_ctime} di
   \var{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 \macro{SETALL}, che per un solo semaforo con \macro{SETVAL}), i
+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.
@@ -2188,10 +2217,10 @@ tutti i semafori il cui valore viene modificato.
     \textbf{Operazione}  & \textbf{Valore restituito} \\
     \hline
     \hline
-    \macro{GETNCNT}& valore di \var{semncnt}.\\
-    \macro{GETPID} & valore di \var{sempid}.\\
-    \macro{GETVAL} & valore di \var{semval}.\\
-    \macro{GETZCNT}& valore di \var{semzcnt}.\\
+    \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}.} 
@@ -2220,21 +2249,21 @@ vengono effettuate con la funzione \func{semop}, il cui prototipo 
   \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[\macro{EACCES}] Il processo non ha i privilegi per eseguire
+    \item[\errcode{EACCES}] Il processo non ha i privilegi per eseguire
       l'operazione richiesta.
-    \item[\macro{EIDRM}] L'insieme di semafori è stato cancellato.
-    \item[\macro{ENOMEM}] Si è richiesto un \macro{SEM\_UNDO} ma il sistema
+    \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[\macro{EAGAIN}] Un'operazione comporterebbe il blocco del processo,
-      ma si è specificato \macro{IPC\_NOWAIT} in \var{sem\_flg}.
-    \item[\macro{EINTR}] La funzione, bloccata in attesa dell'esecuzione
+    \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[\macro{E2BIG}] L'argomento \param{nsops} è maggiore del numero
-      massimo di operazioni \macro{SEMOPM}.
-    \item[\macro{ERANGE}] Per alcune operazioni il valore risultante del
-      semaforo viene a superare il limite massimo \macro{SEMVMX}.
+    \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 \macro{EFAULT} ed \macro{EINVAL}.
+  ed inoltre \errval{EFAULT} ed \errval{EINVAL}.
 }
 \end{functions}
 
@@ -2275,11 +2304,11 @@ 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 \macro{IPC\_NOWAIT} e
-\macro{SEM\_UNDO}.  Impostando \macro{IPC\_NOWAIT} si fa si che, invece di
+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 \macro{EAGAIN}.  Impostando \macro{SEM\_UNDO}
+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.
 
@@ -2289,26 +2318,26 @@ 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 \macro{ERANGE} qualora si sia superato il
-  limite \macro{SEMVMX}) ed il processo non viene bloccato in nessun caso.
-  Specificando \macro{SEM\_UNDO} si aggiorna il contatore per il ripristino
+  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 \macro{IPC\_NOWAIT} la
-  funzione ritorna con un errore di \macro{EAGAIN}, altrimenti viene
+  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 \macro{EIDRM}.
+    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
-    \macro{EINTR}.
+    \errcode{EINTR}.
   \end{itemize*}
   Al processo chiamante è richiesto il privilegio di lettura dell'insieme dei
   semafori.
@@ -2316,24 +2345,24 @@ possibili:
 \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 \macro{SEM\_UNDO} viene anche
+  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 \macro{IPC\_NOWAIT} la funzione ritorna con un
-  errore di \macro{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:
+  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 \macro{SEM\_UNDO} viene aggiornato il contatore per il
+    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 \macro{EIDRM}.
+  \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
-    \macro{EINTR}.
+    \errcode{EINTR}.
   \end{itemize*}    
   Al processo chiamante è richiesto il privilegio di alterazione (scrittura)
   sull'insieme di semafori.
@@ -2347,7 +2376,7 @@ vengono pure aggiornati al tempo corrente i campi \var{sem\_otime} e
 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
-\macro{SEM\_UNDO}. Il meccanismo è implementato tramite una apposita struttura
+\const{SEM\_UNDO}. Il meccanismo è implementato tramite una apposita struttura
 \var{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
@@ -2360,8 +2389,8 @@ occorre fare riferimento all'implementazione usata in Linux, che 
 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 System V IPC è stata modificata, ma le definizioni relative a
-queste strutture restano per compatibilità.\footnote{in particolare con le
+struttura del \textit{SysV IPC} è stata modificata, ma le definizioni relative
+queste strutture restano per compatibilità.\footnote{in particolare con le
   vecchie versioni delle librerie del C, come le libc5.}
 
 \begin{figure}[htb]
@@ -2393,7 +2422,7 @@ viene ripetuto fin quando non ci sono pi
 svuotata la coda.
 
 Per gestire il meccanismo del ripristino tutte le volte che per un'operazione
-si è specificato il flag \macro{SEM\_UNDO} viene mantenuta per ciascun insieme
+si è specificato il flag \const{SEM\_UNDO} viene mantenuta per ciascun insieme
 di semafori una apposita struttura \var{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. 
@@ -2421,12 +2450,156 @@ 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);
+}
+    \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 1--17}) è \func{MutexCreate} che data una
+chiave crea il semaforo usato per il mutex e lo inizializza, restituendone
+l'identificatore. Il primo passo (\texttt{\small 8}) è chiamare \func{semget}
+con \const{IPC\_CREATE} per creare il semaforo qualora non esista,
+assegnandogli i privilegi di lettura e scrittura per tutti. In caso di errore
+(\texttt{\small 9--11}) si ritorna subito il risultato di \func{semget},
+altrimenti (\texttt{\small 12}) si inizializza il semaforo chiamando
+\func{semctl} con il comando \const{SETVAL}, utilizzando l'unione
+\var{semunion} dichiarata ed avvalorata in precedenza (\texttt{\small 6}) ad 1
+per significare che risorsa è libera. In caso di errore (\texttt{\small
+  13--16}) si restituisce il valore di ritorno di \func{semctl}, altrimenti si
+ritorna l'identificatore del semaforo.
+
+La seconda funzione (\texttt{\small 18--24}) è \func{MutexFind}, che data una
+chiave, restituisce l'identificatore del semaforo ad essa associato. La
+comprensione del suo funzionamento è immediata in quanto è solo un
+\textit{wrapper}\footnote{si chiama così una funzione usata per fare da
+  \textsl{involucro} alla chiamata di un altra, usata in genere per
+  semplificare un'interfaccia (come in questo caso) o per utilizzare con la
+  stessa funzione diversi substrati (librerie, ecc.)  che possono fornire le
+  stesse funzionalità.} di \func{semget} per cercare l'identificatore
+associato alla chiave, restituendo direttamente il valore di ritorno della
+funzione.
+
+La terza funzione (\texttt{\small 25--31}) è \func{MutexRead} che, dato
+l'identificatore, restituisce il valore del mutex. Anche in questo caso la
+funzione è un \textit{wrapper} per la chiamata di \func{semctl}, questa volta
+con il comando \const{GETVAL}, che permette di restituire il valore del
+semaforo.
+
+La quarta e la quinta funzione (\texttt{\small 43--56}) sono \func{MutexLock},
+e \func{MutexUnlock}, che permettono rispettivamente di bloccare e sbloccare
+il mutex. Entrambe fanno da wrapper per \func{semop}, utilizzando le due
+strutture \var{sem\_lock} e \var{sem\_unlock} definite in precedenza
+(\texttt{\small 32--42}). Si noti come per queste ultime si sia fatto uso
+dell'opzione \const{SEM\_UNDO} per evitare che il semaforo resti bloccato in
+caso di terminazione imprevista del processo.%%  Si noti infine come, essendo
+%% tutte le funzioni riportate in \figref{fig:ipc_mutex_create} estremamente
+%% semplici, se si sono definite tutte come \ctyp{inline}.\footnote{la direttiva
+%%   \func{inline} viene usata per dire al compilatore di non trattare la
+%%   funzione cui essa fa riferimento come una funzione, ma di inserire il codice
+%%   direttamente nel testo del programma.  Anche se i compilatori più moderni
+%%   sono in grado di effettuare da soli queste manipolazioni (impostando le
+%%   opportune ottimizzazioni) questa è una tecnica usata per migliorare le
+%%   prestazioni per le funzioni piccole ed usate di frequente, in tal caso
+%%   infatti le istruzioni per creare un nuovo frame nello stack per chiamare la
+%%   funzione costituirebbero una parte rilevante del codice, appesantendo
+%%   inutilmente il programma. Originariamente questa era fatto utilizzando delle
+%%   macro, ma queste hanno tutta una serie di problemi di sintassi nel passaggio
+%%   degli argomenti (si veda ad esempio \cite{PratC} che in questo modo possono
+%%   essere evitati.}
+
+
+Chiamare \func{MutexLock} decrementa il valore del semaforo: se questo è
+libero (ha già valore 1) sarà bloccato (valore nullo), se è bloccato la
+chiamata a \func{semop} si bloccherà fintanto che la risorsa non venga
+rilasciata. Chiamando \func{MutexUnlock} il valore del semaforo sarà
+incrementato di uno, sbloccandolo qualora fosse bloccato.  Si noti che occorre
+eseguire sempre prima \func{MutexLock} e poi \func{MutexUnlock}, perché se per
+un qualche errore si esegue più volte quest'ultima il valore del semaforo
+crescerebbe oltre 1, e \func{MutexLock} non avrebbe più l'effetto aspettato
+(bloccare la risorsa quando questa è considerata libera). Si tenga presente
+che usare \func{MutexRead} per controllare il valore dei mutex prima di
+proseguire non servirebbe comunque, dato che l'operazione non sarebbe atomica.
+Vedremo in \secref{sec:ipc_posix_sem} come è possibile ottenere un'interfaccia
+analoga senza questo problemi usando il file locking.
+
+
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_sysv_shm}
 
-Il terzo oggetto introdotto dal \textit{System V IPC} è quello dei segmenti di
-memoria condivisa. La funzione che permette di ottenerne uno è \func{shmget}
+Il terzo oggetto introdotto dal \textit{SysV IPC} è quello dei segmenti di
+memoria condivisa. La funzione che permette di ottenerne uno è \func{shmget},
 ed il suo prototipo è:
 \begin{functions}
   \headdecl{sys/types.h} 
@@ -2440,25 +2613,43 @@ ed il suo prototipo 
   \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
     in caso di errore, nel qual caso \var{errno} assumerà i valori:
     \begin{errlist}
-    \item[\macro{ENOSPC}] Si è superato il limite (\macro{SHMMNI}) sul numero
+    \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 (\macro{SHMALL}) per
+      cui dimensioni fanno superare il limite di sistema (\const{SHMALL}) per
       la memoria ad essi riservata.
-    \item[\macro{EINVAL}] Si è richiesta una dimensione per un nuovo segmento
-      maggiore di \macro{SHMMAX} o minore di \macro{SHMMIN}, o se il segmento
+    \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[\macro{ENOMEM}] Il sistema non ha abbastanza memoria per poter
+    \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 \macro{EACCES}, \macro{ENOENT}, \macro{EEXIST}, \macro{EIDRM},
-    con lo stesso significato che hanno per \func{msgget}.}
+    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} 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 \macro{PAGE\_SIZE}.
+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
@@ -2495,7 +2686,7 @@ invece:
   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\_atime}, che esprimno
+\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
@@ -2507,11 +2698,14 @@ invece:
 \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, i cui valori, riportati in
-\tabref{tab:ipc_shm_limits} sono associati ad altrettante costanti.  Alcuni di
-questi limiti sono al solito accessibili e modificabili attraverso
+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/}.
+\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
@@ -2522,15 +2716,25 @@ questi limiti sono al solito accessibili e modificabili attraverso
     & \textbf{Significato} \\
     \hline
     \hline
-    \macro{SHMALL}&0x200000&\file{shmall}& Numero massimo di pagine che 
+    \const{SHMALL}& 0x200000&\file{shmall}& Numero massimo di pagine che 
                                        possono essere usate per i segmenti di
                                        memoria condivisa. \\
-    \macro{SHMMAX}&0x2000000&\file{shmmax}& Dimensione massima di un segmento 
-                                       di memoria condivisa.\\
-    \macro{SHMMNI}&4096&\file{msgmni}& Numero massimo di segmenti di memoria
-                                       condivisa presenti nel kernel.\\
-    \macro{SHMMIN}&   1& ---         & Dimensione minima di un segmento 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
@@ -2552,73 +2756,504 @@ 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[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma i permessi non
+    \item[\errcode{EACCES}] Si è richiesto \const{IPC\_STAT} ma i permessi non
       consentono l'accesso in lettura al segmento.
-    \item[\macro{EINVAL}] .
-    \item[\macro{ENOMEM}] .
-    \end{errlist}.}
+    \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}
 
-Per utilizzare i segmenti di memoria condivisa si usano due funzioni,
-\func{shmat} e \func{shmdt}, che consentono di agganciarli e sganciarli da un
-processo, così che questo possa vederli nel suo spazio di indirizzi; i loro
-prototipi sono:
+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 \var{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 userid 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 è \func{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
+\var{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, \func{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{Le funzioni restituiscono rispettivamente l'indirizzo del segmento
-    e 0 in caso di successo, mentre entrambe restituiscono -1 in caso di
-    errore, nel qual caso \var{errno} assumerà i valori:
-    \begin{errlist}
-    \item[\macro{EACCES}] Il processo non ha i provilegi di accesso.
-    \item[\macro{EINVAL}] .
-    \item[\macro{EPERM}] Si è è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID}
-      senza avere i permessi del creatore o del proprietario del segmento (o
-      quelli dell'amministratore).
-    \item[\macro{EOVERFLOW}] Si è richiesto \macro{IPC\_STAT} ma alcuni valori
-      sono troppo grandi per essere memorizzati nella struttura puntata da
-      \param{buf}.
-    \end{errlist}
-    ed inoltre \macro{EFAULT} e \macro{EIDRM}.}
+  \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
+\var{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.
+
+
+%% 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 signoli oggetti che ne fan parte, il \textit{SysV IPC}
+presenta numerosi problemi; in \cite{APUE}\footnote{in particolare nel
+  capitolo 14.}  Stevens ne eeffettua 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}) si può
+ottenere lo stesso 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 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 è poco diffuso.
+
+
+
+\subsection{I \textsl{file di lock}}
+\label{sec:ipc_file_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}\index{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.} 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
+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 anche in questo caso, in caso di terminazione
+imprevista del processo, si lascia allocata la risorsa (il file di lock) e
+questa deve essere sempre cancellata esplicitamente.  Inoltre il controllo
+della disponibilità può essere eseguito solo con una tecnica di
+\textit{polling}\index{polling}, ed è quindi molto inefficiente.
+
+La tecnica dei file di lock non di meno ha una sua utilità, e può essere usata
+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.
+
+\subsection{La sincronizzazione con il \textit{file locking}}
+\label{sec:ipc_lock_file}
+
+Dato che i file di lock presentano gli inconvenienti illustrati in precedenza,
+la tecnica alternativa più comune è quella di fare ricorso al \textit{file
+  locking} (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 LockMutex: lock a file (creating it if not existent).  
+ */
+int LockMutex(const char *path_name)
+{
+    int fd, res;
+    struct flock lock;                                /* file lock structure */
+    /* first open the file (creating it if not existent) */
+    if ( (fd = open(path_name, O_EXCL|O_CREAT)) < 0) {    /* first open file */
+        return fd;
+    }
+    /* set flock structure */
+    lock.l_type = F_WRLCK;                        /* set type: read or write */
+    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
+    lock.l_start = 0;                  /* set the start of the locked region */
+    lock.l_len = 0;                   /* set the length of the locked region */
+    /* do locking */
+    if ( (res = fcntl(fd, F_SETLKW, &lock)) < 0 ) {
+        return res;
+    }
+    return 0;
+}
+/*
+ * Function UnLockMutex: unlock a file.  
+ */
+int UnlockMutex(const char *path_name)
+{
+    int fd, res;
+    struct flock lock;                                /* file lock structure */
+    /* first open the file */
+    if ( (fd = open(path_name, O_RDWR)) < 0) {            /* first open file */
+        return fd;
+    }
+    /* set flock structure */
+    lock.l_type = F_UNLCK;                               /* set type: unlock */
+    lock.l_whence = SEEK_SET;        /* start from the beginning of the file */
+    lock.l_start = 0;                  /* set the start of the locked region */
+    lock.l_len = 0;                   /* set the length of the locked region */
+    /* do locking */
+    if ( (res = fcntl(fd, F_SETLK, &lock)) < 0 ) {
+        return res;
+    }
+    return 0;
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Il codice delle funzioni che permettono di creare un
+    \textit{mutex} utilizzando il file locking.}
+  \label{fig:ipc_flock_mutex}
+\end{figure}
+
+Il codice per implementare un mutex utilizzando il file locking è riportato in
+\figref{fig:ipc_flock_mutex}; a differenza del precedente caso in cui si sono
+usati i semafori le funzioni questa volta sono sufficienti due funzioni,
+\func{LockMutex} e \func{UnlockMutex}, usate rispettivamente per acquisire e
+rilasciare il mutex.
+
+La prima funzione (\texttt{\small 1--22}) serve per acquisire il mutex.
+Anzitutto si apre (\texttt{\small 9--11}), creandolo se non esiste, il file
+specificato dall'argomento \param{pathname}. In caso di errore si ritorna
+immediatamente, altrimenti si prosegue impostando (\texttt{\small 12--16}) la
+struttura \var{lock} in modo da poter acquisire un write lock sul file. Infine
+si richiede (\texttt{\small 17--20}) il file lock (restituendo il codice di
+ritorno di \func{fcntl} caso di errore). Se il file è libero il lock è
+acquisito e la funzione ritorna immediatamente; altrimenti \func{fcntl} si
+bloccherà (si noti che la si è chiamata con \func{F\_SETLKW}) fino al rilascio
+del lock.
+
+La seconda funzione (\texttt{\small 23--44}) serve a rilasciare il mutex. Di
+nuovo si apre (\texttt{\small 30--33}) il file specificato dall'argomento
+\param{pathname} (che stavolta deve esistere), ritornando immediatamente in
+caso di errore. Poi si passa ad inizializzare (\texttt{\small 34--38}) la
+struttura \var{lock} per il rilascio del lock, che viene effettuato
+(\texttt{\small 39--42}) subito dopo.
+
+ \subsection{Il \textit{memory mapping} anonimo}
+\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
+  nele \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 supportate a livello del kernel, esse però
+possono essere implementate, usando la memoria condivisa ed i mutex, con
+funzioni di libreria. In generale esse sono comunque poco usate, i socket, nei
+casi in cui sono sufficienti, sono più comodi, e negli altri casi la
+comunicazione può essere gestita direttamente con la stessa metodologia usata
+per implementare le code di messaggi. 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 una 
+
 
 \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"