Revisione e portare tutte le figure ad inconsolata per uniformità con
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 978e3b19e399cad38e84949e380ac68b63530fb9..7e5645de914e3c40a15e64e5a33ff522903e912b 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -1,6 +1,6 @@
 %% ipc.tex
 %%
-%% Copyright (C) 2000-2013 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2014 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 "Un preambolo",
@@ -200,9 +200,9 @@ Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
 delle caratteristiche specifiche, esso infatti non viene lanciato da una
 shell, ma dallo stesso web server, alla richiesta di una specifica URL, che di
 solito ha la forma:
-\begin{Verbatim}
+\begin{Example}
 http://www.sito.it/cgi-bin/programma?argomento
-\end{Verbatim}
+\end{Example}
 ed il risultato dell'elaborazione deve essere presentato (con una intestazione
 che ne descrive il \textit{mime-type}) sullo \textit{standard output}, in modo
 che il server web possa reinviarlo al browser che ha effettuato la richiesta,
@@ -2602,8 +2602,6 @@ delle pagine di swap ad uso del meccanismo del \textit{copy on write}
 significa che caso di scrittura sul segmento quando non c'è più memoria
 disponibile, si avrà l'emissione di un \signal{SIGSEGV}.
 
-% TODO verificare i privilegi necessari per SHM_HUGETLB
-
 Infine l'argomento \param{size} specifica la dimensione del segmento di
 memoria condivisa; il valore deve essere specificato in byte, ma verrà
 comunque arrotondato al multiplo superiore di \const{PAGE\_SIZE}. Il valore
@@ -2783,7 +2781,7 @@ si ha a cuore la portabilità. Questi comandi aggiuntivi sono:
   sez.~\ref{sec:proc_mem_lock} fino al kernel 2.6.9 solo l'amministratore
   poteva utilizzare questa capacità,\footnote{che richiedeva la
     \textit{capability} \const{CAP\_IPC\_LOCK}.} a partire dal dal kernel
-  2.6.10 anche gli utenti normali possono farlo fina al limite massimo
+  2.6.10 anche gli utenti normali possono farlo fino al limite massimo
   determinato da \const{RLIMIT\_MEMLOCK} (vedi
   sez.~\ref{sec:sys_resource_limit}).
 \item[\const{SHM\_UNLOCK}] Disabilita il \itindex{memory~locking}
@@ -2973,7 +2971,7 @@ funzioni di libreria che ne semplifichino l'uso, automatizzando le operazioni
 più comuni; il codice, contenuto nel file \file{SharedMem.c}, è riportato in
 fig.~\ref{fig:ipc_sysv_shm_func}.
 
-La prima funzione (\texttt{\small 3--16}) è \func{ShmCreate} che, data una
+La prima funzione (\texttt{\small 1--16}) è \func{ShmCreate} che, data una
 chiave, crea il segmento di memoria condivisa restituendo il puntatore allo
 stesso. La funzione comincia (\texttt{\small 6}) con il chiamare
 \func{shmget}, usando il flag \const{IPC\_CREATE} per creare il segmento
@@ -3086,7 +3084,7 @@ Il passo successivo (\texttt{\small 30--39}) è quello di creare gli oggetti di
 intercomunicazione necessari. Si inizia costruendo (\texttt{\small 30}) la
 chiave da usare come riferimento con il nome del programma,\footnote{si è
   usato un riferimento relativo alla home dell'utente, supposto che i sorgenti
-  di GaPiL siano stati installati direttamente in essa. Qualora si effettui
+  di GaPiL siano stati installati direttamente in essa; qualora si effettui
   una installazione diversa si dovrà correggere il programma.} dopo di che si
 richiede (\texttt{\small 31}) la creazione di un segmento di memoria condivisa
 con usando la funzione \func{ShmCreate} illustrata in precedenza (una pagina
@@ -3343,7 +3341,7 @@ alternativi.
 La prima possibilità, utilizzata fin dalle origini di Unix, è quella di usare
 dei \textsl{file di lock} (per i quali è stata anche riservata una opportuna
 directory, \file{/var/lock}, nella standardizzazione del \textit{Filesystem
-  Hyerarchy Standard}). Per questo si usa la caratteristica della funzione
+  Hierarchy Standard}). Per questo si usa la caratteristica della funzione
 \func{open} (illustrata in sez.~\ref{sec:file_open_close}) che
 prevede\footnote{questo è quanto dettato dallo standard POSIX.1, ciò non
   toglie che in alcune implementazioni questa tecnica possa non funzionare; in
@@ -3582,7 +3580,7 @@ POSIX prendono come primo argomento una stringa che indica uno di questi nomi;
 lo standard è molto generico riguardo l'implementazione, ed i nomi stessi
 possono avere o meno una corrispondenza sul filesystem; tutto quello che è
 richiesto è che:
-\begin{itemize}
+\begin{itemize*}
 \item i nomi devono essere conformi alle regole che caratterizzano i
   \textit{pathname}, in particolare non essere più lunghi di \const{PATH\_MAX}
   byte e terminati da un carattere nullo.
@@ -3591,7 +3589,7 @@ richiesto è che:
   nome dipende dall'implementazione.
 \item l'interpretazione di ulteriori \texttt{/} presenti nel nome dipende
   dall'implementazione.
-\end{itemize}
+\end{itemize*}
 
 Data la assoluta genericità delle specifiche, il comportamento delle funzioni
 è subordinato in maniera quasi completa alla relativa implementazione, tanto
@@ -3600,65 +3598,61 @@ standard usata dallo standard POSIX per consentire implementazioni non
 standardizzabili. 
 
 Nel caso di Linux, sia per quanto riguarda la memoria condivisa ed i semafori,
-che per quanto riguarda le code di messaggi, tutto viene creato usando come
-radici delle opportune directory (rispettivamente \file{/dev/shm} e
-\file{/dev/mqueue}, per i dettagli si faccia riferimento a
-sez.~\ref{sec:ipc_posix_shm}, sez.~\ref{sec:ipc_posix_sem} e
-sez.~\ref{sec:ipc_posix_mq}) ed i nomi specificati nelle relative funzioni
-sono considerati come un \itindsub{pathname}{assoluto} \textit{pathname}
-assoluto (comprendente eventuali sottodirectory) rispetto a queste radici.
+che per le code di messaggi, tutto viene creato usando come radici delle
+opportune directory (rispettivamente \file{/dev/shm} e \file{/dev/mqueue}, per
+i dettagli si faccia riferimento a sez.~\ref{sec:ipc_posix_shm},
+sez.~\ref{sec:ipc_posix_sem} e sez.~\ref{sec:ipc_posix_mq}).  I nomi
+specificati nelle relative funzioni devono essere nella forma di un
+\textit{pathname} assoluto (devono cioè iniziare con ``\texttt{/}'') e
+corrisponderanno ad altrettanti file creati all'interno di queste directory;
+per questo motivo detti nomi non possono contenere altre ``\texttt{/}'' oltre
+quella iniziale.
 
 Il vantaggio degli oggetti di IPC POSIX è comunque che essi vengono inseriti
 nell'albero dei file, e possono essere maneggiati con le usuali funzioni e
-comandi di accesso ai file, che funzionano come su dei file normali; questo
+comandi di accesso ai file, che funzionano come su dei file normali. Questo
 però è vero nel caso di Linux, che usa una implementazione che lo consente,
 non è detto che altrettanto valga per altri kernel. In particolare, come si
-può facilmente verificare con uno \cmd{strace}, sia per la memoria condivisa
-che per le code di messaggi le system call utilizzate da Linux sono le stesse
-di quelle dei file, essendo detti oggetti realizzati come tali in appositi
-filesystem.
+può facilmente verificare con il comando \cmd{strace}, sia per la memoria
+condivisa che per le code di messaggi varie \textit{system call} utilizzate da
+Linux corrispondono in realtà a quelle ordinarie dei file, essendo detti
+oggetti realizzati come tali in appositi filesystem.
 
 In particolare i permessi associati agli oggetti di IPC POSIX sono identici ai
 permessi dei file, ed il controllo di accesso segue esattamente la stessa
 semantica (quella illustrata in sez.~\ref{sec:file_access_control}), e non
 quella particolare (si ricordi quanto visto in
 sez.~\ref{sec:ipc_sysv_access_control}) che viene usata per gli oggetti del
-SysV-IPC.  Per quanto riguarda l'attribuzione dell'utente e del gruppo
+SysV-IPC. Per quanto riguarda l'attribuzione dell'utente e del gruppo
 proprietari dell'oggetto alla creazione di quest'ultimo essa viene effettuata
 secondo la semantica SysV: corrispondono cioè a \ids{UID} e \ids{GID} effettivi
 del processo che esegue la creazione.
 
 
-\subsection{Code di messaggi}
+\subsection{Code di messaggi Posix}
 \label{sec:ipc_posix_mq}
 
 Le code di messaggi POSIX sono supportate da Linux a partire dalla versione
-2.6.6-rc1 del kernel,\footnote{l'implementazione è dovuta a Michal Wronski e
-  Krzysztof Benedyczak, e le relative informazioni si possono trovare su
-  \url{http://www.geocities.com/wronski12/posix_ipc/index.html}.} In generale,
-come le corrispettive del \textit{SysV-IPC}, le code di messaggi sono poco
-usate, dato che i socket, nei casi in cui sono sufficienti, sono più comodi, e
-che in casi più complessi la comunicazione può essere gestita direttamente con
-mutex (o semafori) e memoria condivisa con tutta la flessibilità che occorre.
+2.6.6 del kernel. In generale, come le corrispettive del \textit{SysV-IPC}, le
+code di messaggi sono poco usate, dato che i socket, nei casi in cui sono
+sufficienti, sono più comodi, e che in casi più complessi la comunicazione può
+essere gestita direttamente con mutex (o semafori) e memoria condivisa con
+tutta la flessibilità che occorre.
 
 Per poter utilizzare le code di messaggi, oltre ad utilizzare un kernel
-superiore al 2.6.6 (o precedente, se sono stati opportunamente applicati i
-relativi patch) occorre utilizzare la libreria \file{libmqueue}\footnote{i
-  programmi che usano le code di messaggi cioè devono essere compilati
-  aggiungendo l'opzione \code{-lmqueue} al comando \cmd{gcc}; in
-  corrispondenza all'inclusione del supporto nel kernel ufficiale anche
-  \file{libmqueue} è stata inserita nella \acr{glibc}, a partire dalla
-  versione 2.3.4 delle medesime.} che contiene le funzioni dell'interfaccia
-POSIX (in realtà l'implementazione è realizzata tramite delle opportune
-chiamate ad \func{ioctl} sui file del filesystem speciale su cui vengono
-mantenuti questi oggetti di IPC).
+superiore al 2.6.6 occorre utilizzare la libreria \file{librt} che contiene le
+funzioni dell'interfaccia POSIX ed i programmi che usano le code di messaggi
+devono essere compilati aggiungendo l'opzione \code{-lrt} al comando
+\cmd{gcc}. In corrispondenza all'inclusione del supporto nel kernel ufficiale
+le funzioni di libreria sono state inserite nella \acr{glibc}, e sono
+disponibili a partire dalla versione 2.3.4 delle medesime.
 
 La libreria inoltre richiede la presenza dell'apposito filesystem di tipo
-\texttt{mqueue} montato su \file{/dev/mqueue}; questo può essere fatto
-aggiungendo ad \conffile{/etc/fstab} una riga come:
-\begin{Example}
+\texttt{mqueue} montato sulla directory \file{/dev/mqueue}; questo può essere
+fatto aggiungendo ad \conffile{/etc/fstab} una riga come:
+\begin{FileExample}[label=/etc/fstab]
 mqueue   /dev/mqueue       mqueue    defaults        0      0
-\end{Example}
+\end{FileExample}
 ed esso sarà utilizzato come radice sulla quale vengono risolti i nomi delle
 code di messaggi che iniziano con una ``\texttt{/}''. Le opzioni di mount
 accettate sono \texttt{uid}, \texttt{gid} e \texttt{mode} che permettono
@@ -3666,10 +3660,12 @@ rispettivamente di impostare l'utente, il gruppo ed i permessi associati al
 filesystem.
 
 
-La funzione che permette di aprire (e crearla se non esiste ancora) una coda
-di messaggi POSIX è \funcd{mq\_open}, ed il suo prototipo è:
+La funzione di sistema che permette di aprire (e crearla se non esiste ancora)
+una coda di messaggi POSIX è \funcd{mq\_open}, ed il suo prototipo è:
 
 \begin{funcproto}{
+\fhead{fcntl.h}
+\fhead{sys/stat.h}
 \fhead{mqueue.h}
 \fdecl{mqd\_t mq\_open(const char *name, int oflag)}
 \fdecl{mqd\_t mq\_open(const char *name, int oflag, unsigned long mode,
@@ -3681,20 +3677,24 @@ di messaggi POSIX è \funcd{mq\_open}, ed il suo prototipo è:
 {La funzione ritorna il descrittore associato alla coda in caso di successo e
   $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
-    \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al
-      alla memoria secondo quanto specificato da \param{oflag}.
-    \item[\errcode{EEXIST}] si è specificato \const{O\_CREAT} e
-      \const{O\_EXCL} ma la coda già esiste.
-    \item[\errcode{EINVAL}] il file non supporta la funzione, o si è
-      specificato \const{O\_CREAT} con una valore non nullo di \param{attr} e
-      valori non validi di \var{mq\_maxmsg} e \var{mq\_msgsize}.
-    \item[\errcode{ENOENT}] non si è specificato \const{O\_CREAT} ma la coda
-      non esiste.
+  \item[\errcode{EACCES}] il processo non ha i privilegi per accedere alla
+    coda secondo quanto specificato da \param{oflag} oppure \const{name}
+    contiene più di una ``\texttt{/}''.
+  \item[\errcode{EEXIST}] si è specificato \const{O\_CREAT} e \const{O\_EXCL}
+    ma la coda già esiste.
+  \item[\errcode{EINVAL}] il file non supporta la funzione, o si è specificato
+    \const{O\_CREAT} con una valore non nullo di \param{attr} e valori non
+    validi dei campi \var{mq\_maxmsg} e \var{mq\_msgsize}; questi valori
+    devono essere positivi ed inferiori ai limiti di sistema se il processo
+    non ha privilegi amministrativi, inoltre \var{mq\_maxmsg} non può comunque
+    superare \const{HARD\_MAX}.
+  \item[\errcode{ENOENT}] non si è specificato \const{O\_CREAT} ma la coda non
+    esiste o si è usato il nome ``\texttt{/}''.
+  \item[\errcode{ENOSPC}] lo spazio è insufficiente, probabilmente per aver
+    superato il limite di \texttt{queues\_max}.
   \end{errlist}
-  ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT},
-  \errval{EMFILE}, \errval{EINTR} ed \errval{ENFILE} nel loro significato
-  generico.
-}  
+  ed inoltre \errval{EMFILE}, \errval{ENAMETOOLONG}, \errval{ENFILE},
+  \errval{ENOMEM} ed nel loro significato generico.  }
 \end{funcproto}
 
 La funzione apre la coda di messaggi identificata dall'argomento \param{name}
@@ -3704,15 +3704,19 @@ descriptor, con l'unica differenza che lo standard prevede un apposito tipo
 file descriptor; pertanto, anche se questo comportamento non è portabile, lo
 si può tenere sotto osservazione con le funzioni dell'I/O multiplexing (vedi
 sez.~\ref{sec:file_multiplexing}) come possibile alternativa all'uso
-dell'interfaccia di notifica di \func{mq\_notify} (che vedremo a breve). Se la
-coda esiste già il descrittore farà riferimento allo stesso oggetto,
-consentendo così la comunicazione fra due processi diversi.
+dell'interfaccia di notifica di \func{mq\_notify} (che vedremo a breve).
+
+Se il nome indicato fa riferimento ad una coda di messaggi già esistente, il
+descrittore ottenuto farà riferimento allo stesso oggetto, pertanto tutti i
+processi che hanno usato \func{mq\_open} su quel nome otterranno un
+riferimento alla stessa coda. Diventa così immediato costruire un canale di
+comunicazione fra detti processi.
 
 La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
 possono essere specificati per \param{oflag}, che deve essere specificato come
 maschera binaria; i valori possibili per i vari bit sono quelli visti in
-sez.~\ref{sec:file_open_close} dei quali però \func{mq\_open} riconosce solo i
-seguenti:
+sez.~\ref{sec:file_open_close} (per questo occorre includere \texttt{fcntl.h})
+dei quali però \func{mq\_open} riconosce solo i seguenti:
 \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
 \item[\const{O\_RDONLY}] Apre la coda solo per la ricezione di messaggi. Il
   processo potrà usare il descrittore con \func{mq\_receive} ma non con
@@ -3744,11 +3748,13 @@ Se la coda non esiste e la si vuole creare si deve specificare
 creazione con l'argomento \param{mode};\footnote{fino al 2.6.14 per un bug i
   valori della \textit{umask} del processo non venivano applicati a questi
   permessi.} i valori di quest'ultimo sono identici a quelli usati per
-\func{open}, anche se per le code di messaggi han senso solo i permessi di
-lettura e scrittura. Oltre ai permessi di creazione possono essere specificati
-anche gli attributi specifici della coda tramite l'argomento \param{attr};
-quest'ultimo è un puntatore ad una apposita struttura \struct{mq\_attr}, la
-cui definizione è riportata in fig.~\ref{fig:ipc_mq_attr}.
+\func{open} (per questo occorre includere \texttt{sys/stat.h}), anche se per
+le code di messaggi han senso solo i permessi di lettura e scrittura.
+
+Oltre ai permessi di creazione possono essere specificati anche gli attributi
+specifici della coda tramite l'argomento \param{attr}; quest'ultimo è un
+puntatore ad una apposita struttura \struct{mq\_attr}, la cui definizione è
+riportata in fig.~\ref{fig:ipc_mq_attr}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -3765,10 +3771,46 @@ Per la creazione della coda i campi della struttura che devono essere
 specificati sono \var{mq\_maxmsg} e \var{mq\_msgsize}, che indicano
 rispettivamente il numero massimo di messaggi che può contenere e la
 dimensione massima di un messaggio. Il valore dovrà essere positivo e minore
-dei rispettivi limiti di sistema \const{MQ\_MAXMSG} e \const{MQ\_MSGSIZE},
-altrimenti la funzione fallirà con un errore di \errcode{EINVAL}.
-Se \param{attr} è un puntatore nullo gli attributi della coda saranno
-impostati ai valori predefiniti.
+dei rispettivi limiti di sistema altrimenti la funzione fallirà con un errore
+di \errcode{EINVAL}.  Se \param{attr} è un puntatore nullo gli attributi della
+coda saranno impostati ai valori predefiniti.
+
+I suddetti limiti di sistema sono impostati attraverso altrettanti file in
+\texttt{/proc/sys/fs/mqueue}, in particolare i file che controllano i valori
+dei limiti sono:
+\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
+\item[\sysctlfile{fs/mqueue/msg\_max}] Indica il valore massimo del numero di
+  messaggi in una coda e agisce come limite superiore per il valore di
+  \var{attr->mq\_maxmsg} in \func{mq\_open}. Il suo valore di default è 10. Il
+  valore massimo è \const{HARD\_MAX} che vale \code{(131072/sizeof(void *))},
+  ed il valore minimo 1 (ma era 10 per i kernel precedenti il 2.6.28). Questo
+  limite viene ignorato per i processi con privilegi amministrativi (più
+  precisamente con la \itindex{capability} \textit{capability}
+  \const{CAP\_SYS\_RESOURCE}) ma \const{HARD\_MAX} resta comunque non
+  superabile.
+
+\item[\sysctlfile{fs/mqueue/msgsize\_max}] Indica il valore massimo della
+  dimensione in byte di un messaggio sulla coda ed agisce come limite
+  superiore per il valore di \var{attr->mq\_msgsize} in \func{mq\_open}. Il
+  suo valore di default è 8192.  Il valore massimo è 1048576 ed il valore
+  minimo 128 (ma per i kernel precedenti il 2.6.28 detti limiti erano
+  rispettivamente \const{INT\_MAX} e 8192). Questo limite viene ignorato dai
+  processi con privilegi amministrativi (con la \itindex{capability}
+  \textit{capability} \const{CAP\_SYS\_RESOURCE}).
+
+\item[\sysctlfile{fs/mqueue/queues\_max}] Indica il numero massimo di code di
+  messaggi creabili in totale sul sistema, il valore di default è 256 ma si
+  può usare un valore qualunque fra $0$ e \const{INT\_MAX}. Il limite non
+  viene applicato ai processi con privilegi amministrativi (cioè con la
+  \itindex{capability} \textit{capability} \const{CAP\_SYS\_RESOURCE}).
+
+\end{basedescript}
+
+Infine sulle code di messaggi si applica il limite imposto sulla risorsa
+\const{RLIMIT\_MSGQUEUE} (vedi sez.~\ref{sec:sys_resource_limit}) che indica
+lo spazio massimo (in byte) occupabile dall'insieme di tutte le code di
+messaggi appartenenti ai processi di uno stesso utente, che viene identificato
+in base al \textit{real user ID} degli stessi.
 
 Quando l'accesso alla coda non è più necessario si può chiudere il relativo
 descrittore con la funzione \funcd{mq\_close}, il cui prototipo è:
@@ -3786,18 +3828,20 @@ descrittore con la funzione \funcd{mq\_close}, il cui prototipo è:
 }  
 \end{funcproto}
 
-La funzione è analoga a \func{close} (e in Linux, dove le code sono
-implementate come file su un filesystem dedicato, è esattamente la stessa
-funzione) dopo la sua esecuzione il processo non sarà più in grado di usare il
-descrittore della coda, ma quest'ultima continuerà ad esistere nel sistema e
-potrà essere acceduta con un'altra chiamata a \func{mq\_open}. All'uscita di
-un processo tutte le code aperte, così come i file, vengono chiuse
-automaticamente. Inoltre se il processo aveva agganciato una richiesta di
-notifica sul descrittore che viene chiuso, questa sarà rilasciata e potrà
-essere richiesta da qualche altro processo.
+La funzione è analoga a \func{close},\footnote{su Linux, dove le code sono
+  implementate come file su un filesystem dedicato, è esattamente la stessa
+  funzione, per cui non esiste una \textit{system call} autonoma e la funzione
+  viene rimappata su \func{close} dalle \acr{glibc}.}  dopo la sua esecuzione
+il processo non sarà più in grado di usare il descrittore della coda, ma
+quest'ultima continuerà ad esistere nel sistema e potrà essere acceduta con
+un'altra chiamata a \func{mq\_open}. All'uscita di un processo tutte le code
+aperte, così come i file, vengono chiuse automaticamente. Inoltre se il
+processo aveva agganciato una richiesta di notifica sul descrittore che viene
+chiuso, questa sarà rilasciata e potrà essere richiesta da qualche altro
+processo.
 
 Quando si vuole effettivamente rimuovere una coda dal sistema occorre usare la
-funzione \funcd{mq\_unlink}, il cui prototipo è:
+funzione di sistema \funcd{mq\_unlink}, il cui prototipo è:
 
 \begin{funcproto}{
 \fhead{mqueue.h}
@@ -3807,14 +3851,21 @@ funzione \funcd{mq\_unlink}, il cui prototipo è:
 }
 
 {La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
-  caso \var{errno} assumerà gli stessi valori riportati da \func{unlink}.
+  caso \var{errno} assumerà gli uno dei valori:
+  \begin{errlist}
+    \item[\errcode{EACCES}] non si hanno i permessi per cancellare la coda.
+    \item[\errcode{ENAMETOOLONG}] il nome indicato è troppo lungo.
+    \item[\errcode{ENOENT}] non esiste una coda con il nome indicato.
+  \end{errlist}
 }  
 \end{funcproto}
 
 Anche in questo caso il comportamento della funzione è analogo a quello di
-\func{unlink} per i file, (e di nuovo l'implementazione di Linux usa
-direttamente \func{unlink}) la funzione rimuove la coda \param{name}, così che
-una successiva chiamata a \func{mq\_open} fallisce o crea una coda diversa.
+\func{unlink} per i file, la funzione rimuove la coda \param{name} (ed il
+relativo file sotto \texttt{/dev/mqueue}), così che una successiva chiamata a
+\func{mq\_open} fallisce o crea una coda diversa.
+
+% TODO, verificare se mq_unlink è davvero una system call indipendente.
 
 Come per i file ogni coda di messaggi ha un contatore di riferimenti, per cui
 la coda non viene effettivamente rimossa dal sistema fin quando questo non si
@@ -3824,7 +3875,7 @@ di essa.  Allo stesso modo una coda ed i suoi contenuti resteranno disponibili
 all'interno del sistema anche quando quest'ultima non è aperta da nessun
 processo (questa è una delle differenze più rilevanti nei confronti di
 \textit{pipe} e \textit{fifo}).  La sola differenza fra code di messaggi POSIX
-e file normali è che, essendo il filesystem delle code di messaggi virtuale e
+e file normali è che, essendo il filesystem delle code di messaggi virtuale, e
 basato su oggetti interni al kernel, il suo contenuto viene perduto con il
 riavvio del sistema.
 
@@ -3840,41 +3891,52 @@ funzioni \funcd{mq\_getattr} e \funcd{mq\_setattr}, i cui prototipi sono:
     struct mq\_attr *omqstat)}
 \fdesc{Modifica gli attributi di una coda di messaggi POSIX.}
 }
-
-{Entrambe le funzioni ritornano $0$ in caso di successo e $-1$ per un errore,
+{
+Entrambe le funzioni ritornano $0$ in caso di successo e $-1$ per un errore,
   nel qual caso \var{errno} assumerà i valori \errval{EBADF}
     o \errval{EINVAL} nel loro significato generico.
 }  
 \end{funcproto}
 
 La funzione \func{mq\_getattr} legge i valori correnti degli attributi della
-coda nella struttura puntata da \param{mqstat}; di questi l'unico relativo
-allo stato corrente della coda è \var{mq\_curmsgs} che indica il numero di
-messaggi da essa contenuti, gli altri indicano le caratteristiche generali
-della stessa.
+coda \param{mqdes} nella struttura \struct{mq\_attr} puntata
+da \param{mqstat}; di questi l'unico relativo allo stato corrente della coda è
+\var{mq\_curmsgs} che indica il numero di messaggi da essa contenuti, gli
+altri indicano le caratteristiche generali della stessa impostate in fase di
+apertura.
 
 La funzione \func{mq\_setattr} permette di modificare gli attributi di una
-coda tramite i valori contenuti nella struttura puntata da \param{mqstat}, ma
-può essere modificato solo il campo \var{mq\_flags}, gli altri campi vengono
-ignorati. In particolare i valori di \var{mq\_maxmsg} e \var{mq\_msgsize}
-possono essere specificati solo in fase ci creazione della coda.  Inoltre i
-soli valori possibili per \var{mq\_flags} sono 0 e \const{O\_NONBLOCK}, per
-cui alla fine la funzione può essere utilizzata solo per abilitare o
-disabilitare la modalità non bloccante. L'argomento \param{omqstat} viene
-usato, quando diverso da \val{NULL}, per specificare l'indirizzo di una
-struttura su cui salvare i valori degli attributi precedenti alla chiamata
-della funzione.
-
-Per inserire messaggi su di una coda sono previste due funzioni,
-\funcd{mq\_send} e \funcd{mq\_timedsend}, i cui prototipi sono:
+coda (indicata da \param{mqdes}) tramite i valori contenuti nella struttura
+\struct{mq\_attr} puntata da \param{mqstat}, ma può essere modificato solo il
+campo \var{mq\_flags}, gli altri campi vengono comunque ignorati.
+
+In particolare i valori di \var{mq\_maxmsg} e \var{mq\_msgsize} possono essere
+specificati solo in fase ci creazione della coda.  Inoltre i soli valori
+possibili per \var{mq\_flags} sono 0 e \const{O\_NONBLOCK}, per cui alla fine
+la funzione può essere utilizzata solo per abilitare o disabilitare la
+modalità non bloccante. L'argomento \param{omqstat} viene usato, quando
+diverso da \val{NULL}, per specificare l'indirizzo di una struttura su cui
+salvare i valori degli attributi precedenti alla chiamata della funzione.
+
+Per inserire messaggi su di una coda sono previste due funzioni di sistema,
+\funcd{mq\_send} e \funcd{mq\_timedsend}. In realtà su Linux la \textit{system
+  call} è soltanto \func{mq\_timedsend}, mentre \func{mq\_send} viene
+implementata come funzione di libreria che si appoggia alla
+precedente. Inoltre \func{mq\_timedsend} richiede che sia definita la macro
+\macro{\_XOPEN\_SOURCE} ad un valore pari ad almeno \texttt{600} o la macro
+\macro{\_POSIX\_C\_SOURCE} ad un valore uguale o maggiore di \texttt{200112L}.
+I rispettivi prototipi sono:
 
 \begin{funcproto}{
 \fhead{mqueue.h}
 \fdecl{int mq\_send(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len,
     unsigned int msg\_prio)}
 \fdesc{Esegue l'inserimento di un messaggio su una coda.}
+\fhead{mqueue.h}
+\fhead{time.h}
 \fdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t
-    msg\_len, unsigned msg\_prio, const struct timespec *abs\_timeout)}
+    msg\_len, unsigned int msg\_prio,\\ 
+\phantom{int mq\_timedsend(}const struct timespec *abs\_timeout)}
 \fdesc{Esegue l'inserimento di un messaggio su una coda entro un tempo
   specificato}
 }
@@ -3884,83 +3946,92 @@ Per inserire messaggi su di una coda sono previste due funzioni,
   \begin{errlist}
     \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la
       coda è piena.
-    \item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len}
-      eccede il limite impostato per la coda.
+    \item[\errcode{EBADF}] si specificato un file descriptor non valido.
     \item[\errcode{EINVAL}] si è specificato un valore nullo per
       \param{msg\_len}, o un valore di \param{msg\_prio} fuori dai limiti, o
       un valore non valido per \param{abs\_timeout}.
+    \item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len}
+      eccede il limite impostato per la coda.
     \item[\errcode{ETIMEDOUT}] l'inserimento del messaggio non è stato
-      effettuato entro il tempo stabilito.
+      effettuato entro il tempo stabilito (solo \func{mq\_timedsend}).
   \end{errlist}
-  ed inoltre \errval{EBADF}, \errval{ENOMEM} ed \errval{EINTR} nel loro
-  significato generico.
+  ed inoltre \errval{EBADF} e \errval{EINTR} nel loro significato generico.
 }
 \end{funcproto}
 
-Entrambe le funzioni richiedono un puntatore al testo del messaggio
-nell'argomento \param{msg\_ptr} e la relativa lunghezza in \param{msg\_len}.
+Entrambe le funzioni richiedono un puntatore ad un buffer in memoria
+contenente il testo del messaggio da inserire nella coda \param{mqdes}
+nell'argomento \param{msg\_ptr}, e la relativa lunghezza in \param{msg\_len}.
 Se quest'ultima eccede la dimensione massima specificata da \var{mq\_msgsize}
 le funzioni ritornano immediatamente con un errore di \errcode{EMSGSIZE}.
 
-L'argomento \param{msg\_prio} indica la priorità dell'argomento; i messaggi di
-priorità maggiore vengono inseriti davanti a quelli di priorità inferiore (e
-quindi saranno riletti per primi). A parità del valore della priorità il
-messaggio sarà inserito in coda a tutti quelli con la stessa priorità. Il
-valore della priorità non può eccedere il limite di sistema
-\const{MQ\_PRIO\_MAX}, che nel caso è pari a 32768.
+L'argomento \param{msg\_prio} indica la priorità dell'argomento, che, essendo
+definito come \ctyp{unsigned int}, è sempre un intero positivo. I messaggi di
+priorità maggiore vengono inseriti davanti a quelli di priorità inferiore, e
+quindi saranno riletti per primi. A parità del valore della priorità il
+messaggio sarà inserito in coda a tutti quelli che hanno la stessa priorità
+che quindi saranno letti con la politica di una \textit{fifo}. Il valore della
+priorità non può eccedere il limite di sistema \const{MQ\_PRIO\_MAX}, che al
+momento è pari a 32768.
 
 Qualora la coda sia piena, entrambe le funzioni si bloccano, a meno che non
-sia stata selezionata in fase di apertura la modalità non
-bloccante,\footnote{o si sia impostato il flag \const{O\_NONBLOCK} sul file
-  descriptor della coda.} nel qual caso entrambe ritornano \errcode{EAGAIN}.
-La sola differenza fra le due funzioni è che la seconda, passato il tempo
-massimo impostato con l'argomento \param{abs\_timeout},\footnote{deve essere
-  specificato un tempo assoluto tramite una struttura \struct{timespec} (vedi
-  fig.~\ref{fig:sys_timespec_struct}) indicato in numero di secondi e
-  nanosecondi a partire dal 1 gennaio 1970.} ritorna comunque con un errore di
-\errcode{ETIMEDOUT}, se invece il tempo è già scaduto al momento della
-chiamata e la coda è vuota la funzione ritorna immediatamente.
+sia stata selezionata in fase di apertura della stessa la modalità non
+bloccante o non si sia impostato il flag \const{O\_NONBLOCK} sul file
+descriptor della coda, nel qual caso entrambe ritornano con un codice di
+errore di \errcode{EAGAIN}.
+
+La sola differenza fra le due funzioni è che \func{mq\_timedsend}, passato il
+tempo massimo impostato con l'argomento \param{abs\_timeout}, ritorna con un
+errore di \errcode{ETIMEDOUT}, se invece il tempo è già scaduto al momento
+della chiamata e la coda è piena la funzione ritorna immediatamente. Il valore
+di \param{abs\_timeout} deve essere specificato come tempo assoluto tramite
+una struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timespec_struct})
+indicato in numero di secondi e nanosecondi a partire dal 1 gennaio 1970.
 
 Come per l'inserimento, anche per l'estrazione dei messaggi da una coda sono
-previste due funzioni, \funcd{mq\_receive} e \funcd{mq\_timedreceive}, i cui
-prototipi sono:
-\begin{functions}
-  \headdecl{mqueue.h} 
-  
-  \funcdecl{ssize\_t mq\_receive(mqd\_t mqdes, char *msg\_ptr, size\_t
-    msg\_len, unsigned int *msg\_prio)}   
-  Effettua la ricezione di un messaggio da una coda.
-  
-  \funcdecl{ssize\_t mq\_timedreceive(mqd\_t mqdes, char *msg\_ptr, size\_t
-    msg\_len, unsigned int *msg\_prio, const struct timespec *abs\_timeout)}
-  Effettua la ricezione di un messaggio da una coda entro il tempo
-  \param{abs\_timeout}.
-  
-  \bodydesc{Le funzioni restituiscono il numero di byte del messaggio in caso
-    di successo e -1 in caso di errore; nel quel caso \var{errno} assumerà i
-    valori:
-    \begin{errlist}
+previste due funzioni di sistema, \funcd{mq\_receive} e
+\funcd{mq\_timedreceive}. Anche in questo caso su Linux soltanto
+\func{mq\_timedreceive} è effettivamente, una \textit{system call} e per
+usarla devono essere definite le opportune macro come per
+\func{mq\_timedsend}. I rispettivi prototipi sono:
+
+\begin{funcproto}{
+\fhead{mqueue.h} 
+\fdecl{ssize\_t mq\_receive(mqd\_t mqdes, char *msg\_ptr, size\_t
+    msg\_len, unsigned int *msg\_prio)} 
+\fdesc{Effettua la ricezione di un messaggio da una coda.}
+\fhead{mqueue.h} 
+\fhead{time.h} 
+\fdecl{ssize\_t mq\_timedreceive(mqd\_t mqdes, char *msg\_ptr, size\_t
+    msg\_len,\\ 
+\phantom{ssize\_t  mq\_timedreceive(}unsigned int *msg\_prio, const struct timespec
+*abs\_timeout)} 
+\fdesc{Riceve un messaggio da una coda entro un limite di tempo.}
+}
+{Entrambe le funzioni ritornano il numero di byte del messaggio in caso di
+  successo e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei
+  valori:
+  \begin{errlist}
     \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la
       coda è vuota.
-    \item[\errcode{EMSGSIZE}] la lunghezza del messaggio sulla coda eccede il
-      valore \param{msg\_len} specificato per la ricezione.
     \item[\errcode{EINVAL}] si è specificato un valore nullo per
       \param{msg\_ptr}, o un valore non valido per \param{abs\_timeout}.
+    \item[\errcode{EMSGSIZE}] la lunghezza del messaggio sulla coda eccede il
+      valore \param{msg\_len} specificato per la ricezione.
     \item[\errcode{ETIMEDOUT}] la ricezione del messaggio non è stata
       effettuata entro il tempo stabilito.
-    \end{errlist}    
-    ed inoltre \errval{EBADF}, \errval{EINTR}, \errval{ENOMEM}, o
-    \errval{EINVAL}.}
-\end{functions}
-
-La funzione estrae dalla coda il messaggio a priorità più alta, o il più
-vecchio fra quelli della stessa priorità. Una volta ricevuto il messaggio
-viene tolto dalla coda e la sua dimensione viene restituita come valore di
-ritorno.\footnote{si tenga presente che 0 è una dimensione valida e che la
-  condizione di errore è restituita dal valore -1; Stevens in \cite{UNP2} fa
-  notare che questo è uno dei casi in cui vale ciò che lo standard
-  \textsl{non} dice, una dimensione nulla infatti, pur non essendo citata, non
-  viene proibita.}
+  \end{errlist}
+  ed inoltre \errval{EBADF} o \errval{EINTR} nel loro significato generico.  }
+\end{funcproto}
+
+La funzione estrae dalla coda \param{mqdes} il messaggio a priorità più alta,
+o il più vecchio fra quelli della stessa priorità. Una volta ricevuto il
+messaggio viene tolto dalla coda e la sua dimensione viene restituita come
+valore di ritorno; si tenga presente che 0 è una dimensione valida e che la
+condizione di errore è indicata soltanto da un valore di
+$-1$.\footnote{Stevens in \cite{UNP2} fa notare che questo è uno dei casi in
+  cui vale ciò che lo standard \textsl{non} dice, una dimensione nulla
+  infatti, pur non essendo citata, non viene proibita.}
 
 Se la dimensione specificata da \param{msg\_len} non è sufficiente a contenere
 il messaggio, entrambe le funzioni, al contrario di quanto avveniva nelle code
@@ -3981,8 +4052,6 @@ selezionare quale messaggio estrarre con delle condizioni sulla priorità, a
 differenza di quanto avveniva con le code di messaggi di SysV che permettono
 invece la selezione in base al valore del campo \var{mtype}. 
 
-% TODO inserire i dati di /proc/sys/fs/mqueue 
-
 Qualora la coda sia vuota entrambe le funzioni si bloccano, a meno che non si
 sia selezionata la modalità non bloccante; in tal caso entrambe ritornano
 immediatamente con l'errore \errcode{EAGAIN}. Anche in questo caso la sola
@@ -4002,39 +4071,47 @@ superare in parte questo problema.
 Una caratteristica specifica delle code di messaggi POSIX è la possibilità di
 usufruire di un meccanismo di notifica asincrono; questo può essere attivato
 usando la funzione \funcd{mq\_notify}, il cui prototipo è:
-\begin{prototype}{mqueue.h}
-{int mq\_notify(mqd\_t mqdes, const struct sigevent *notification)}
 
-Attiva il meccanismo di notifica per la coda \param{mqdes}.
-  
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
-  errore; nel quel caso \var{errno} assumerà i valori: 
-    \begin{errlist}
-    \item[\errcode{EBUSY}] c'è già un processo registrato per la notifica.
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_notify(mqd\_t mqdes, const struct sigevent *notification)}
+
+\fdesc{Attiva il meccanismo di notifica per una coda.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
     \item[\errcode{EBADF}] il descrittore non fa riferimento ad una coda di
       messaggi.
-    \end{errlist}}
-\end{prototype}
+    \item[\errcode{EBUSY}] c'è già un processo registrato per la notifica.
+    \item[\errcode{EINVAL}] si è richiesto un meccanismo di notifica invalido
+      o specificato nella notifica con i segnali il valore di un segnale non
+      esistente.
+  \end{errlist}
+  ed inoltre \errval{ENOMEM} nel suo significato generico.
+}  
+\end{funcproto}
 
 Il meccanismo di notifica permette di segnalare in maniera asincrona ad un
-processo la presenza di dati sulla coda, in modo da evitare la necessità di
-bloccarsi nell'attesa. Per far questo un processo deve registrarsi con la
-funzione \func{mq\_notify}, ed il meccanismo è disponibile per un solo
-processo alla volta per ciascuna coda.
+processo la presenza di dati sulla coda indicata da \param{mqdes}, in modo da
+evitare la necessità di bloccarsi nell'attesa. Per far questo un processo deve
+registrarsi con la funzione \func{mq\_notify}, ed il meccanismo è disponibile
+per un solo processo alla volta per ciascuna coda.
 
-Il comportamento di \func{mq\_notify} dipende dal valore dell'argomento
-\param{notification}, che è un puntatore ad una apposita struttura
+Il comportamento di \func{mq\_notify} dipende dai valori passati con
+l'argomento \param{notification}, che è un puntatore ad una apposita struttura
 \struct{sigevent}, (definita in fig.~\ref{fig:struct_sigevent}) introdotta
 dallo standard POSIX.1b per gestire la notifica di eventi; per altri dettagli
-si può vedere quanto detto in sez.~\ref{sec:sig_timer_adv} a proposito
-dell'uso della stessa struttura per la notifica delle scadenze dei
+su di essa si può rivedere quanto detto in sez.~\ref{sec:sig_timer_adv} a
+proposito dell'uso della stessa struttura per la notifica delle scadenze dei
 \textit{timer}.
 
 Attraverso questa struttura si possono impostare le modalità con cui viene
 effettuata la notifica nel campo \var{sigev\_notify}, che può assumere i
-valori di tab.~\ref{tab:sigevent_sigev_notify}.\footnote{la pagina di manuale
-  riporta soltanto i primi tre (inizialmente era possibile solo
-  \const{SIGEV\_SIGNAL}).} Il metodo consigliato è quello di usare
+valori di tab.~\ref{tab:sigevent_sigev_notify}; fra questi la pagina di
+manuale riporta soltanto i primi tre, ed inizialmente era possibile solo
+\const{SIGEV\_SIGNAL}. Il metodo consigliato è quello di usare
 \const{SIGEV\_SIGNAL} usando il campo \var{sigev\_signo} per indicare il quale
 segnale deve essere inviato al processo. Inoltre il campo \var{sigev\_value} è
 un puntatore ad una struttura \struct{sigval} (definita in
@@ -4048,12 +4125,12 @@ La funzione registra il processo chiamante per la notifica se
 \param{notification} punta ad una struttura \struct{sigevent} opportunamente
 inizializzata, o cancella una precedente registrazione se è \val{NULL}. Dato
 che un solo processo alla volta può essere registrato, la funzione fallisce
-con \errcode{EBUSY} se c'è un altro processo già registrato.\footnote{questo
-  significa anche che se si registra una notifica con \const{SIGEV\_NONE} il
-  processo non la riceverà, ma impedirà anche che altri possano registrarsi
-  per poterlo fare.}  Si tenga presente inoltre che alla chiusura del
-descrittore associato alla coda (e quindi anche all'uscita del processo) ogni
-eventuale registrazione di notifica presente viene cancellata.
+con \errcode{EBUSY} se c'è un altro processo già registrato. Questo significa
+anche che se si registra una notifica con \const{SIGEV\_NONE} il processo non
+la riceverà, ma impedirà anche che altri possano registrarsi per poterlo fare.
+Si tenga presente inoltre che alla chiusura del descrittore associato alla
+coda (e quindi anche all'uscita del processo) ogni eventuale registrazione di
+notifica presente viene cancellata.
 
 La notifica del segnale avviene all'arrivo di un messaggio in una coda vuota
 (cioè solo se sulla coda non ci sono messaggi) e se non c'è nessun processo
@@ -4068,8 +4145,8 @@ la coda diventa disponibile per una ulteriore registrazione.  Questo comporta
 che se si vuole mantenere il meccanismo di notifica occorre ripetere la
 registrazione chiamando nuovamente \func{mq\_notify} all'interno del gestore
 del segnale di notifica. A differenza della situazione simile che si aveva con
-i segnali non affidabili,\footnote{l'argomento è stato affrontato in
-  \ref{sec:sig_semantics}.} questa caratteristica non configura una
+i segnali non affidabili (l'argomento è stato affrontato in
+\ref{sec:sig_semantics}) questa caratteristica non configura una
 \itindex{race~condition} \textit{race condition} perché l'invio di un segnale
 avviene solo se la coda è vuota; pertanto se si vuole evitare di correre il
 rischio di perdere eventuali ulteriori segnali inviati nel lasso di tempo che
@@ -4080,13 +4157,12 @@ L'invio del segnale di notifica avvalora alcuni campi di informazione
 restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in
 fig.~\ref{fig:sig_siginfo_t}). In particolare \var{si\_pid} viene impostato al
 valore del \ids{PID} del processo che ha emesso il segnale, \var{si\_uid}
-all'userid effettivo, \var{si\_code} a \const{SI\_MESGQ}, e \var{si\_errno} a
-0. Questo ci dice che, se si effettua la ricezione dei messaggi usando
-esclusivamente il meccanismo di notifica, è possibile ottenere le informazioni
-sul processo che ha inserito un messaggio usando un gestore per il segnale in
-forma estesa.\footnote{di nuovo si faccia riferimento a quanto detto al
-  proposito in sez.~\ref{sec:sig_sigaction} e sez.~\ref{sec:sig_real_time}.}
-
+all'\textsl{user-ID} effettivo, \var{si\_code} a \const{SI\_MESGQ}, e
+\var{si\_errno} a 0. Questo ci dice che, se si effettua la ricezione dei
+messaggi usando esclusivamente il meccanismo di notifica, è possibile ottenere
+le informazioni sul processo che ha inserito un messaggio usando un gestore
+per il segnale in forma estesa, di nuovo si faccia riferimento a quanto detto
+al proposito in sez.~\ref{sec:sig_sigaction} e sez.~\ref{sec:sig_real_time}.
 
 
 \subsection{Memoria condivisa}
@@ -4099,18 +4175,19 @@ suoi contenuti in memoria, che viene attivato abilitando l'opzione
 \texttt{CONFIG\_TMPFS} in fase di compilazione del kernel.
 
 Per potere utilizzare l'interfaccia POSIX per la memoria condivisa la
-\acr{glibc}\footnote{le funzioni sono state introdotte con la versione 2.2.}
-richiede di compilare i programmi con l'opzione \code{-lrt}; inoltre è
-necessario che in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs};
-questo di norma viene fatto aggiungendo una riga del tipo di:
-\begin{verbatim}
+\acr{glibc} (le funzioni sono state introdotte con la versione 2.2) richiede
+di compilare i programmi con l'opzione \code{-lrt}; inoltre è necessario che
+in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs}; questo di norma
+viene fatto aggiungendo una riga del tipo di:
+\begin{FileExample}[label=/etc/fstab]
 tmpfs   /dev/shm        tmpfs   defaults        0      0
-\end{verbatim}
-ad \conffile{/etc/fstab}. In realtà si può montare un filesystem \texttt{tmpfs}
-dove si vuole, per usarlo come RAM disk, con un comando del tipo:
-\begin{verbatim}
+\end{FileExample}
+ad \conffile{/etc/fstab}. In realtà si può montare un filesystem
+\texttt{tmpfs} dove si vuole, per usarlo come RAM disk, con un comando del
+tipo:
+\begin{Example}
 mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs
-\end{verbatim}
+\end{Example}
 
 Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e
 \texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne
@@ -4121,24 +4198,35 @@ questo caso è l'unità di allocazione elementare.
 La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed
 eventualmente di crearlo se non esiste ancora, è \funcd{shm\_open}; il suo
 prototipo è:
-\begin{functions}
-  \headdecl{sys/mman.h} 
-  \headdecl{sys/stat.h} 
-  \headdecl{fcntl.h} 
 
-  \funcdecl{int shm\_open(const char *name, int oflag, mode\_t mode)} 
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fhead{sys/stat.h}
+\fhead{fcntl.h}
+\fdecl{int shm\_open(const char *name, int oflag, mode\_t mode)}
+
+\fdesc{Apre un segmento di memoria condivisa.}
+}
+
+{La funzione ritorna un file descriptor in caso di successo e $-1$ per un
+  errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EACCES}] non si hanno i permessi di aprire il segmento nella
+    modalità scelta o si richiesto \const{O\_TRUNC} per un segmento su cui non
+    si ha il permesso di scrittura.
+  \item[\errcode{EINVAL}] si è utilizzato un nome non valido.
+  \end{errlist}
+  ed inoltre \errval{EEXIST}, \errval{EMFILE}, \errval{ENAMETOOLONG},
+  \errval{ENFILE} e \errval{ENOENT} nello stesso significato che hanno per
+  \func{open}.
+}  
+\end{funcproto}
 
-  Apre un segmento di memoria condivisa.
-  
-  \bodydesc{La funzione restituisce un file descriptor positivo in caso di
-    successo e -1 in caso di errore; nel quel caso \var{errno} assumerà gli
-    stessi valori riportati da \func{open}.}
-\end{functions}
 
 La funzione apre un segmento di memoria condivisa identificato dal nome
 \param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo
 nome può essere specificato in forma standard solo facendolo iniziare per
-``\file{/}'' e senza ulteriori ``\file{/}''. Linux supporta comunque nomi
+``\texttt{/}'' e senza ulteriori ``\texttt{/}''. Linux supporta comunque nomi
 generici, che verranno interpretati prendendo come radice
 \file{/dev/shm}.\footnote{occorre pertanto evitare di specificare qualcosa del
   tipo \file{/dev/shm/nome} all'interno di \param{name}, perché questo
@@ -4168,36 +4256,52 @@ i seguenti:
 \end{basedescript}
 
 In caso di successo la funzione restituisce un file descriptor associato al
-segmento di memoria condiviso con le stesse modalità di
-\func{open}\footnote{in realtà, come accennato, \func{shm\_open} è un semplice
-  wrapper per \func{open}, usare direttamente quest'ultima avrebbe lo stesso
-  effetto.}  viste in sez.~\ref{sec:file_open_close}; in particolare viene impostato
-il flag \const{FD\_CLOEXEC}.  Chiamate effettuate da diversi processi usando
-lo stesso nome, restituiranno file descriptor associati allo stesso segmento
-(così come, nel caso di file di dati, essi sono associati allo stesso
-\itindex{inode} inode).  In questo modo è possibile effettuare una chiamata ad
-\func{mmap} sul file descriptor restituito da \func{shm\_open} ed i processi
-vedranno lo stesso segmento di memoria condivisa.
-
-Quando il nome non esiste il segmento può essere creato specificando
+segmento di memoria condiviso con le stesse modalità di \func{open} viste in
+sez.~\ref{sec:file_open_close}. Inoltre sul file descriptor viene sempre
+impostato il flag \const{FD\_CLOEXEC}.  Chiamate effettuate da diversi
+processi usando lo stesso nome restituiranno file descriptor associati allo
+stesso segmento, così come, nel caso di file ordinari, essi sono associati
+allo stesso \itindex{inode} inode. In questo modo è possibile effettuare una
+chiamata ad \func{mmap} sul file descriptor restituito da \func{shm\_open} ed
+i processi vedranno lo stesso segmento di memoria condivisa.
+
+Quando il nome non esiste si può creare un nuovo segmento specificando
 \const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file)
-lunghezza nulla. Dato che un segmento di lunghezza nulla è di scarsa utilità,
-per impostarne la dimensione si deve usare \func{ftruncate} (vedi
-sez.~\ref{sec:file_file_size}), prima di mapparlo in memoria con \func{mmap}.
-Si tenga presente che una volta chiamata \func{mmap} si può chiudere il file
-descriptor (con \func{close}), senza che la mappatura ne risenta.
-
-Come per i file, quando si vuole effettivamente rimuovere segmento di memoria
-condivisa, occorre usare la funzione \funcd{shm\_unlink}, il cui prototipo è:
-\begin{prototype}{sys/mman.h}
-{int shm\_unlink(const char *name)}
-
-Rimuove un segmento di memoria condivisa.
-  
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
-  errore; nel quel caso \var{errno} assumerà gli stessi valori riportati da
-  \func{unlink}.}
-\end{prototype}
+lunghezza nulla. Il nuovo segmento verrà creato con i permessi indicati
+da \param{mode} (di cui vengono usati solo i 9 bit meno significativi, non si
+applicano pertanto i permessi speciali di sez.~\ref{sec:file_special_perm})
+filtrati dal valore dell'\textit{umask} del processo. Come gruppo ed utente
+propritario del segmento saranno presi quelli facenti parte del gruppo
+\textit{effective} del processo chiamante.
+
+Dato che un segmento di lunghezza nulla è di scarsa utilità, una vola che lo
+si è creato per impostarne la dimensione si devrà poi usare \func{ftruncate}
+(vedi sez.~\ref{sec:file_file_size}) prima di mapparlo in memoria con
+\func{mmap}.  Si tenga presente che una volta chiamata \func{mmap} si può
+chiudere il file descriptor ad esso associato (semplicemente con
+\func{close}), senza che la mappatura ne risenta, e che questa può essere
+rimossa usando \func{munmap}.
+
+Come per i file, quando si vuole rimuovere completamente un segmento di
+memoria condivisa occorre usare la funzione \funcd{shm\_unlink}, il cui
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{int shm\_unlink(const char *name)}
+
+\fdesc{Rimuove un segmento di memoria condivisa.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EACCES}] non si è proprietari del segmento.
+  \end{errlist}
+  ed inoltre \errval{ENAMETOOLONG} e \errval{ENOENT}, nel loro significato
+  generico.
+}  
+\end{funcproto}
 
 La funzione è del tutto analoga ad \func{unlink}, e si limita a cancellare il
 nome del segmento da \file{/dev/shm}, senza nessun effetto né sui file
@@ -4209,7 +4313,21 @@ con lo stesso nome, la chiamata a \func{shm\_open} fallirà, a meno di non aver
 usato \const{O\_CREAT}, in quest'ultimo caso comunque si otterrà un file
 descriptor che fa riferimento ad un segmento distinto da eventuali precedenti.
 
-\begin{figure}[!htbp]
+Dato che i segmenti di memoria condivisa sono trattati come file del
+filesystem \texttt{tmpfs}, si possono usare su di essi, con lo stesso
+significato che assumono sui file ordinari, anche funzioni come quelle delle
+famiglie \func{fstat}, \func{fchown} e \func{fchmod}. Inoltre a partire dal
+kernel 2.6.19 per i permessi sono supportate anche le ACL illustrate in
+sez.~\ref{sec:file_ACL}.
+
+Come esempio dell'uso delle funzioni attinenti ai segmenti di memoria
+condivisa POSIX, vediamo come è possibile riscrivere una interfaccia
+semplificata analoga a quella vista in fig.~\ref{fig:ipc_sysv_shm_func} per la
+memoria condivisa in stile SysV. Il codice completo, di cui si sono riportate
+le parti esseziali in fig.~\ref{fig:ipc_posix_shmmem}, è contenuto nel file
+\file{SharedMem.c} dei sorgenti allegati.
+
+\begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{\codesamplewidth}
     \includecodesample{listati/MemShared.c}
@@ -4220,39 +4338,33 @@ descriptor che fa riferimento ad un segmento distinto da eventuali precedenti.
   \label{fig:ipc_posix_shmmem}
 \end{figure}
 
-Come esempio per l'uso di queste funzioni vediamo come è possibile riscrivere
-una interfaccia semplificata analoga a quella vista in
-fig.~\ref{fig:ipc_sysv_shm_func} per la memoria condivisa in stile SysV. Il
-codice, riportato in fig.~\ref{fig:ipc_posix_shmmem}, è sempre contenuto nel
-file \file{SharedMem.c} dei sorgenti allegati.
-
 La prima funzione (\texttt{\small 1--24}) è \func{CreateShm} che, dato un nome
 nell'argomento \var{name} crea un nuovo segmento di memoria condivisa,
 accessibile in lettura e scrittura, e ne restituisce l'indirizzo. Anzitutto si
 definiscono (\texttt{\small 8}) i flag per la successiva (\texttt{\small 9})
 chiamata a \func{shm\_open}, che apre il segmento in lettura e scrittura
 (creandolo se non esiste, ed uscendo in caso contrario) assegnandogli sul
-filesystem i permessi specificati dall'argomento \var{perm}. In caso di errore
-(\texttt{\small 10--12}) si restituisce un puntatore nullo, altrimenti si
-prosegue impostando (\texttt{\small 14}) la dimensione del segmento con
-\func{ftruncate}. Di nuovo (\texttt{\small 15--16}) si esce immediatamente
-restituendo un puntatore nullo in caso di errore. Poi si passa (\texttt{\small
-  18}) a mappare in memoria il segmento con \func{mmap} specificando dei
-diritti di accesso corrispondenti alla modalità di apertura.  Di nuovo si
-restituisce (\texttt{\small 19--21}) un puntatore nullo in caso di errore,
-altrimenti si inizializza (\texttt{\small 22}) il contenuto del segmento al
-valore specificato dall'argomento \var{fill} con \func{memset}, e se ne
-restituisce (\texttt{\small 23}) l'indirizzo.
+filesystem i permessi specificati dall'argomento \var{perm}. 
+
+In caso di errore (\texttt{\small 10--12}) si restituisce un puntatore nullo,
+altrimenti si prosegue impostando (\texttt{\small 14}) la dimensione del
+segmento con \func{ftruncate}. Di nuovo (\texttt{\small 15--16}) si esce
+immediatamente restituendo un puntatore nullo in caso di errore. Poi si passa
+(\texttt{\small 18}) a mappare in memoria il segmento con \func{mmap}
+specificando dei diritti di accesso corrispondenti alla modalità di apertura.
+Di nuovo si restituisce (\texttt{\small 19--21}) un puntatore nullo in caso di
+errore, altrimenti si inizializza (\texttt{\small 22}) il contenuto del
+segmento al valore specificato dall'argomento \var{fill} con \func{memset}, e
+se ne restituisce (\texttt{\small 23}) l'indirizzo.
 
 La seconda funzione (\texttt{\small 25--40}) è \func{FindShm} che trova un
-segmento di memoria condiviso già esistente, restituendone l'indirizzo. In
-questo caso si apre (\texttt{\small 31}) il segmento con \func{shm\_open}
-richiedendo che il segmento sia già esistente, in caso di errore
-(\texttt{\small 31--33}) si ritorna immediatamente un puntatore nullo.
-Ottenuto il file descriptor del segmento lo si mappa (\texttt{\small 35}) in
-memoria con \func{mmap}, restituendo (\texttt{\small 36--38}) un puntatore
-nullo in caso di errore, o l'indirizzo (\texttt{\small 39}) dello stesso in
-caso di successo.
+segmento di memoria condiviso esistente, restituendone l'indirizzo. In questo
+caso si apre (\texttt{\small 31}) il segmento con \func{shm\_open} richiedendo
+che il segmento sia già esistente, in caso di errore (\texttt{\small 31--33})
+si ritorna immediatamente un puntatore nullo.  Ottenuto il file descriptor del
+segmento lo si mappa (\texttt{\small 35}) in memoria con \func{mmap},
+restituendo (\texttt{\small 36--38}) un puntatore nullo in caso di errore, o
+l'indirizzo (\texttt{\small 39}) dello stesso in caso di successo.
 
 La terza funzione (\texttt{\small 40--45}) è \func{RemoveShm}, e serve a
 cancellare un segmento di memoria condivisa. Dato che al contrario di quanto
@@ -4273,66 +4385,76 @@ dei semafori POSIX che li realizzava solo a livello di \itindex{thread}
   erano visibili solo all'interno dei \itindex{thread} \textit{thread} creati
   da un singolo processo, e non potevano essere usati come meccanismo di
   sincronizzazione fra processi diversi.} fornita attraverso la sezione delle
-estensioni \textit{real-time} della \acr{glibc}.\footnote{quelle che si
-  accedono collegandosi alla libreria \texttt{librt}.} Esisteva inoltre una
-libreria che realizzava (parzialmente) l'interfaccia POSIX usando le funzioni
-dei semafori di \textit{SysV-IPC} (mantenendo così tutti i problemi
-sottolineati in sez.~\ref{sec:ipc_sysv_sem}).
+estensioni \textit{real-time} della \acr{glibc} (quelle che si accedono
+collegandosi alla libreria \texttt{librt}). Esisteva inoltre una libreria che
+realizzava (parzialmente) l'interfaccia POSIX usando le funzioni dei semafori
+di \textit{SysV-IPC} (mantenendo così tutti i problemi sottolineati in
+sez.~\ref{sec:ipc_sysv_sem}).
 
 A partire dal kernel 2.5.7 è stato introdotto un meccanismo di
-sincronizzazione completamente nuovo, basato sui cosiddetti
-\textit{futex},\footnote{la sigla sta per \textit{fast user mode mutex}.} con
-il quale è stato possibile implementare una versione nativa dei semafori
-POSIX.  Grazie a questo con i kernel della serie 2.6 e le nuove versioni della
-\acr{glibc} che usano questa nuova infrastruttura per quella che viene che
-viene chiamata \textit{New Posix Thread Library}, sono state implementate
-anche tutte le funzioni dell'interfaccia dei semafori POSIX.
+sincronizzazione completamente nuovo, basato sui cosiddetti \textit{futex} (la
+sigla sta per \textit{fast user mode mutex}) con il quale è stato possibile
+implementare una versione nativa dei semafori POSIX.  Grazie a questo con i
+kernel della serie 2.6 e le nuove versioni della \acr{glibc} che usano questa
+nuova infrastruttura per quella che viene che viene chiamata \textit{New Posix
+  Thread Library}, sono state implementate anche tutte le funzioni
+dell'interfaccia dei semafori POSIX.
 
 Anche in questo caso è necessario appoggiarsi alla libreria per le estensioni
 \textit{real-time} \texttt{librt}, questo significa che se si vuole utilizzare
 questa interfaccia, oltre ad utilizzare gli opportuni file di definizione,
-occorrerà compilare i programmi con l'opzione \texttt{-lrt}. 
+occorrerà compilare i programmi con l'opzione \texttt{-lrt} o con
+\texttt{-lpthread} se si usano questi ultimi. 
 
 La funzione che permette di creare un nuovo semaforo POSIX, creando il
 relativo file, o di accedere ad uno esistente, è \funcd{sem\_open}, questa
 prevede due forme diverse a seconda che sia utilizzata per aprire un semaforo
 esistente o per crearne uno nuovi, i relativi prototipi sono:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{sem\_t *sem\_open(const char *name, int oflag)}
-  
-  \funcdecl{sem\_t *sem\_open(const char *name, int oflag, mode\_t mode,
+
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fhead{sys/stat.h}
+\fhead{fcntl.h}
+\fdecl{sem\_t *sem\_open(const char *name, int oflag)}
+\fdecl{sem\_t *sem\_open(const char *name, int oflag, mode\_t mode,
     unsigned int value)} 
 
-  Crea un semaforo o ne apre uno esistente.
-  
-  \bodydesc{La funzione restituisce l'indirizzo del semaforo in caso di
-    successo e \const{SEM\_FAILED} in caso di errore; nel quel caso
-    \var{errno} assumerà i valori:
-    \begin{errlist}
+\fdesc{Crea un semaforo o ne apre uno esistente.}
+}
+{La funzione ritorna l'indirizzo del semaforo in caso di successo e
+  \const{SEM\_FAILED} per un errore, nel qual caso \var{errno} assumerà uno
+  dei valori:
+  \begin{errlist}
     \item[\errcode{EACCES}] il semaforo esiste ma non si hanno permessi
       sufficienti per accedervi.
     \item[\errcode{EEXIST}] si sono specificati \const{O\_CREAT} e
       \const{O\_EXCL} ma il semaforo esiste.
     \item[\errcode{EINVAL}] il valore di \param{value} eccede
-      \const{SEM\_VALUE\_MAX}.
+      \const{SEM\_VALUE\_MAX} o il nome è solo ``\texttt{/}''.
     \item[\errcode{ENAMETOOLONG}] si è utilizzato un nome troppo lungo.
     \item[\errcode{ENOENT}] non si è usato \const{O\_CREAT} ed il nome
       specificato non esiste.
-    \end{errlist}    
-    ed inoltre \errval{ENFILE} ed \errval{ENOMEM}.}
-\end{functions}
+  \end{errlist}
+  ed inoltre \errval{EMFILE}, \errval{ENFILE} ed \errval{ENOMEM} nel loro
+  significato generico.
+
+}
+\end{funcproto}
 
 L'argomento \param{name} definisce il nome del semaforo che si vuole
 utilizzare, ed è quello che permette a processi diversi di accedere allo
-stesso semaforo. Questo deve essere specificato con un \textit{pathname} nella
-forma \texttt{/qualchenome}, che non ha una corrispondenza diretta con un
-\textit{pathname} reale; con Linux infatti i file associati ai semafori sono
-mantenuti nel filesystem virtuale \texttt{/dev/shm}, e gli viene assegnato
-automaticamente un nome nella forma \texttt{sem.qualchenome}.\footnote{si ha
-  cioè una corrispondenza per cui \texttt{/qualchenome} viene rimappato, nella
-  creazione tramite \func{sem\_open}, su \texttt{/dev/shm/sem.qualchenome}.}
+stesso semaforo. Questo deve essere specificato nella stessa forma utilizzata
+per i segmenti di memoria condivisa, con un nome che inizia con ``\texttt{/}''
+e senza ulteriori ``\texttt{/}'', vale a dire nella forma
+\texttt{/nomesemaforo}.
+
+Con Linux i file associati ai semafori sono mantenuti nel filesystem virtuale
+\texttt{/dev/shm}, e gli viene assegnato automaticamente un nome nella forma
+\texttt{sem.nomesemaforo}, si ha cioè una corrispondenza per cui
+\texttt{/nomesemaforo} viene rimappato, nella creazione tramite
+\func{sem\_open}, su \texttt{/dev/shm/sem.nomesemaforo}. Per questo motivo la
+dimensione massima per il nome di un semaforo, a differenza di quanto avviene
+per i segmenti di memoria confivisa, è pari a \const{NAME\_MAX}$ - 4$.
 
 L'argomento \param{oflag} è quello che controlla le modalità con cui opera la
 funzione, ed è passato come maschera binaria; i bit corrispondono a quelli
@@ -4347,26 +4469,25 @@ funzione, in cui si devono specificare sia un valore iniziale con l'argomento
   quanto avviene per i semafori del \textit{SysV-IPC}, effettuare in maniera
   atomica creazione ed inizializzazione di un semaforo usando una unica
   funzione.} che una maschera dei permessi con l'argomento
-\param{mode};\footnote{anche questo argomento prende gli stessi valori
-  utilizzati per l'analogo di \func{open}, che si sono illustrati in dettaglio
-  sez.~\ref{sec:file_perm_overview}.} questi verranno assegnati al semaforo
-appena creato. Se il semaforo esiste già i suddetti valori saranno invece
+\param{mode}; se il semaforo esiste già questi saranno semplicemente
 ignorati. Usando il flag \const{O\_EXCL} si richiede invece la verifica che il
-semaforo non esiste, usandolo insieme ad \const{O\_CREAT} la funzione fallisce
-qualora un semaforo con lo stesso nome sia già presente.
+semaforo non esista, ed usandolo insieme ad \const{O\_CREAT} la funzione
+fallisce qualora un semaforo con lo stesso nome sia già presente.
+
+Si tenga presente che, come accennato in sez.~\ref{sec:ipc_posix_generic}, i
+semafori usano la semantica standard dei file per quanto riguarda i controlli
+di accesso, questo significa che un nuovo semaforo viene sempre creato con
+l'\ids{UID} ed il \ids{GID} effettivo del processo chiamante, e che i permessi
+indicati con \param{mode} vengono filtrati dal valore della \itindex{umask}
+\textit{umask} del processo.  Inoltre per poter aprire un semaforo è
+necessario avere su di esso sia il permesso di lettura che quello di
+scrittura.
 
 La funzione restituisce in caso di successo un puntatore all'indirizzo del
 semaforo con un valore di tipo \ctyp{sem\_t *}, è questo valore che dovrà
-essere passato alle altre funzioni per operare sul semaforo stesso. Si tenga
-presente che, come accennato in sez.~\ref{sec:ipc_posix_generic}, i semafori
-usano la semantica standard dei file per quanto riguarda i controlli di
-accesso. 
-
-Questo significa che un nuovo semaforo viene sempre creato con l'\ids{UID} ed
-il \ids{GID} effettivo del processo chiamante, e che i permessi indicati con
-\param{mode} vengono filtrati dal valore della \itindex{umask} \textit{umask}
-del processo.  Inoltre per poter aprire un semaforo è necessario avere su di
-esso sia il permesso di lettura che quello di scrittura.
+essere passato alle altre funzioni per operare sul semaforo stesso, e non sarà
+più necessario fare riferimento al nome, che potrebbe anche essere rimosso con
+\func{sem\_unlink}.
 
 Una volta che si sia ottenuto l'indirizzo di un semaforo, sarà possibile
 utilizzarlo; se si ricorda quanto detto all'inizio di
@@ -4375,57 +4496,63 @@ relativi ai semafori, le operazioni principali sono due, quella che richiede
 l'uso di una risorsa bloccando il semaforo e quella che rilascia la risorsa
 liberando il semaforo. La prima operazione è effettuata dalla funzione
 \funcd{sem\_wait}, il cui prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{int sem\_wait(sem\_t *sem)}
-  
-  Blocca il semaforo \param{sem}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà i valori:
-    \begin{errlist}
+
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fdecl{int sem\_wait(sem\_t *sem)}
+
+\fdesc{Blocca un semaforo.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
     \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
     \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
-    \end{errlist}    
-}
-\end{functions}
+  \end{errlist}
+}  
+\end{funcproto}
 
 La funzione cerca di decrementare il valore del semaforo indicato dal
 puntatore \param{sem}, se questo ha un valore positivo, cosa che significa che
 la risorsa è disponibile, la funzione ha successo, il valore del semaforo
-viene diminuito di 1 ed essa ritorna immediatamente; se il valore è nullo la
-funzione si blocca fintanto che il valore del semaforo non torni
-positivo\footnote{ovviamente per opera di altro processo che lo rilascia
-  chiamando \func{sem\_post}.} così che poi essa possa decrementarlo con
-successo e proseguire. 
-
-Si tenga presente che la funzione può sempre essere interrotta da un segnale
-(nel qual caso si avrà un errore di \const{EINTR}) e che questo avverrà
-comunque, anche se si è richiesta la semantica BSD installando il relativo
-gestore con \const{SA\_RESTART} (vedi sez.~\ref{sec:sig_sigaction}) per
-riavviare le system call interrotte.
+viene diminuito di 1 ed essa ritorna immediatamente consentendo la
+prosecuzione del processo.
+
+Se invece il valore è nullo la funzione si blocca (fermando l'esecuzione del
+processo) fintanto che il valore del semaforo non ritorna positivo (cosa che a
+questo punto può avvenire solo per opera di altro processo che rilascia il
+semaforo con una chiamata a \func{sem\_post}) così che poi essa possa
+decrementarlo con successo e proseguire.
+
+Si tenga presente che la funzione può sempre essere interrotta da un segnale,
+nel qual caso si avrà un errore di \const{EINTR}; inoltre questo avverrà
+comunque, anche qualora si fosse richiesta la gesione con la semantica BSD,
+installando il gestore del suddetto segnale con l'opzione \const{SA\_RESTART}
+(vedi sez.~\ref{sec:sig_sigaction}) per riavviare le \textit{system call}
+interrotte.
 
 Della funzione \func{sem\_wait} esistono due varianti che consentono di
 gestire diversamente le modalità di attesa in caso di risorsa occupata, la
 prima di queste è \funcd{sem\_trywait}, che serve ad effettuare un tentativo
 di acquisizione senza bloccarsi; il suo prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{int sem\_trywait(sem\_t *sem)}
-  
-  Tenta di bloccare il semaforo \param{sem}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà gli stessi valori:
-    \begin{errlist}
+
+\begin{funcproto}{
+\fhead{semaphore.h} 
+\fdecl{int sem\_trywait(sem\_t *sem)}
+
+\fdesc{Tenta di bloccare un semaforo.}
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
     \item[\errcode{EAGAIN}] il semaforo non può essere acquisito senza
       bloccarsi. 
-    \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
-    \end{errlist}    
+    \item[\errcode{EINVAL}] l'argomento \param{sem} non indica un semaforo
+      valido.
+  \end{errlist}
 }
-\end{functions}
+\end{funcproto}
 
 La funzione è identica a \func{sem\_wait} ed se la risorsa è libera ha lo
 stesso effetto, vale a dire che in caso di semaforo diverso da zero la
@@ -4436,77 +4563,88 @@ programma possa proseguire.
 
 La seconda variante di \func{sem\_wait} è una estensione specifica che può
 essere utilizzata soltanto se viene definita la macro \macro{\_XOPEN\_SOURCE}
-ad un valore di 600 prima di includere \headfile{semaphore.h}, la funzione è
-\funcd{sem\_timedwait}, ed il suo prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
+ad un valore di almeno 600 o la macro \macro{\_POSIX\_C\_SOURCE} ad un valore
+uguale o maggiore di \texttt{200112L} prima di includere
+\headfile{semaphore.h}, la funzione è \funcd{sem\_timedwait}, ed il suo
+prototipo è:
 
-  \funcdecl{int sem\_timedwait(sem\_t *sem, const struct timespec
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fdecl{int sem\_timedwait(sem\_t *sem, const struct timespec
     *abs\_timeout)}
-  
-  Blocca il semaforo \param{sem}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà gli stessi valori:
-    \begin{errlist}
-    \item[\errcode{ETIMEDOUT}] è scaduto il tempo massimo di attesa. 
-    \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
-    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
-    \end{errlist}    
+
+\fdesc{Blocca un semaforo.}
 }
-\end{functions}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+    \item[\errcode{EINVAL}] l'argomento \param{sem} non indica un semaforo
+      valido.
+    \item[\errcode{ETIMEDOUT}] è scaduto il tempo massimo di attesa. 
+  \end{errlist}
+}  
+\end{funcproto}
 
 Anche in questo caso il comportamento della funzione è identico a quello di
-\func{sem\_wait}, la sola differenza consiste nel fatto che con questa
-funzione è possibile impostare tramite l'argomento \param{abs\_timeout} un
-tempo limite per l'attesa, scaduto il quale la funzione ritorna comunque,
-anche se non è possibile acquisire il semaforo. In tal caso la funzione
-fallirà, riportando un errore di \errval{ETIMEDOUT}.
-
-La seconda funzione principale utilizzata per l'uso dei semafori è
-\funcd{sem\_post}, che viene usata per rilasciare un semaforo occupato o, in
-generale, per aumentare di una unità il valore dello stesso anche qualora non
-fosse occupato;\footnote{si ricordi che in generale un semaforo viene usato
-  come indicatore di un numero di risorse disponibili.} il suo prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{int sem\_post(sem\_t *sem)}
-  
-  Rilascia il semaforo \param{sem}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà i valori:
-    \begin{errlist}
-    \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
-    \end{errlist}    
+\func{sem\_wait}, ma è possibile impostare un tempo limite per l'attesa
+tramite la struttura \struct{timespec} (vedi
+fig.~\ref{fig:sys_timespec_struct}) puntata
+dall'argomento \param{abs\_timeout}, indicato in secondi e nonosecondi a
+partire dalla cosiddetta \textit{Epoch} (00:00:00, 1 January 1970
+UTC). Scaduto il limite la funzione ritorna anche se non è possibile acquisire
+il semaforo fallendo con un errore di \errval{ETIMEDOUT}.
+
+La seconda funzione principale utilizzata per l'uso dei semafori è quella che
+viene usata per rilasciare un semaforo occupato o, in generale, per aumentare
+di una unità il valore dello stesso anche qualora non fosse occupato (si
+ricordi che in generale un semaforo viene usato come indicatore di un numero
+di risorse disponibili). Detta funzione è \funcd{sem\_post} ed il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fdecl{int sem\_post(sem\_t *sem)}
+
+\fdesc{Rilascia un semaforo.}
 }
-\end{functions}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+    \item[\errcode{EINVAL}] l'argomento \param{sem} non indica un semaforo
+      valido.
+    \item[\errcode{EOVERFLOW}] si superato il massimo valore di un semaforo.
+  \end{errlist}
+}  
+\end{funcproto}
 
 La funzione incrementa di uno il valore corrente del semaforo indicato
 dall'argomento \param{sem}, se questo era nullo la relativa risorsa risulterà
 sbloccata, cosicché un altro processo (o \itindex{thread} \textit{thread})
-eventualmente bloccato in una \func{sem\_wait} sul semaforo potrà essere
+eventualmente bloccato in una \func{sem\_wait} sul semaforo possa essere
 svegliato e rimesso in esecuzione.  Si tenga presente che la funzione è sicura
 \index{funzioni!sicure} per l'uso all'interno di un gestore di segnali (si
 ricordi quanto detto in sez.~\ref{sec:sig_signal_handler}).
 
-Se invece di operare su un semaforo se ne vuole solamente leggere il valore,
-si può usare la funzione \funcd{sem\_getvalue}, il cui prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{int sem\_getvalue(sem\_t *sem, int *sval)}
-  
-  Richiede il valore del semaforo \param{sem}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà i valori:
-    \begin{errlist}
-    \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
-    \end{errlist}    
+Se invece di operare su un semaforo se ne volesse semplicemente leggere il
+valore, si potrà usare la funzione \funcd{sem\_getvalue}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fdecl{int sem\_getvalue(sem\_t *sem, int *sval)}
+
+\fdesc{Richiede il valore di un semaforo.}
 }
-\end{functions}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+    \item[\errcode{EINVAL}] l'argomento \param{sem} non indica un semaforo
+      valido.
+  \end{errlist}
+}  
+\end{funcproto}
 
 La funzione legge il valore del semaforo indicato dall'argomento \param{sem} e
 lo restituisce nella variabile intera puntata dall'argomento
@@ -4524,34 +4662,38 @@ essere già stato modificato al ritorno della funzione.
 
 Una volta che non ci sia più la necessità di operare su un semaforo se ne può
 terminare l'uso con la funzione \funcd{sem\_close}, il cui prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{int sem\_close(sem\_t *sem)}
-  
-  Chiude il semaforo \param{sem}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà i valori:
-    \begin{errlist}
-    \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
-    \end{errlist}    
+
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fdecl{int sem\_close(sem\_t *sem)}
+
+\fdesc{Chiude un semaforo.}
 }
-\end{functions}
-
-La funzione chiude il semaforo indicato dall'argomento \param{sem}; questo
-comporta che tutte le risorse che il sistema può avere assegnato al processo
-nell'uso dello stesso vengono rilasciate. Questo significa che un altro
-processo bloccato sul semaforo a causa della acquisizione da parte del
-processo che chiama \func{sem\_close} potrà essere riavviato.
-
-Si tenga presente poi che come per i file all'uscita di un processo tutti i
-semafori che questo aveva aperto vengono automaticamente chiusi; questo
-comportamento risolve il problema che si aveva con i semafori del \textit{SysV
-  IPC} (di cui si è parlato in sez.~\ref{sec:ipc_sysv_sem}) per i quali le
-risorse possono restare bloccate. Si tenga poi presente che, a differenza di
-quanto avviene per i file, in caso di una chiamata ad \func{execve} tutti i
-semafori vengono chiusi automaticamente.
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+    \item[\errcode{EINVAL}] l'argomento \param{sem} non indica un semaforo
+      valido.
+  \end{errlist}
+}  
+\end{funcproto}
+
+La funzione chiude il semaforo indicato dall'argomento \param{sem}, che non
+potrà più essere utilizzato nelle altre funzioni. La chiusura comporta anche
+che tutte le risorse che il sistema poteva avere assegnato al processo
+nell'uso del semaforo vengono immediatamente rilasciate. Questo significa che
+un eventuale altro processo bloccato sul semaforo a causa della acquisizione
+dello stesso da parte del processo che chiama \func{sem\_close} potrà essere
+immediatamente riavviato.
+
+Si tenga presente poi che come avviene per i file, all'uscita di un processo
+anche tutti i semafori che questo aveva aperto vengono automaticamente chiusi.
+Questo comportamento risolve il problema che si aveva con i semafori del
+\textit{SysV IPC} (di cui si è parlato in sez.~\ref{sec:ipc_sysv_sem}) per i
+quali le risorse possono restare bloccate. Si tenga infine presente che, a
+differenza di quanto avviene per i file, in caso di una chiamata ad
+\func{execve} tutti i semafori vengono chiusi automaticamente.
 
 Come per i semafori del \textit{SysV-IPC} anche quelli POSIX hanno una
 persistenza di sistema; questo significa che una volta che si è creato un
@@ -4559,23 +4701,24 @@ semaforo con \func{sem\_open} questo continuerà ad esistere fintanto che il
 kernel resta attivo (vale a dire fino ad un successivo riavvio) a meno che non
 lo si cancelli esplicitamente. Per far questo si può utilizzare la funzione
 \funcd{sem\_unlink}, il cui prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{int sem\_unlink(const char *name)}
-  
-  Rimuove il semaforo \param{name}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà i valori:
-    \begin{errlist}
+
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fdecl{int sem\_unlink(const char *name)}
+
+\fdesc{Rimuove un semaforo.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
     \item[\errcode{EACCES}] non si hanno i permessi necessari a cancellare il
       semaforo.
     \item[\errcode{ENAMETOOLONG}] il nome indicato è troppo lungo.
     \item[\errcode{ENOENT}] il semaforo \param{name} non esiste.
-    \end{errlist}    
-}
-\end{functions}
+  \end{errlist}
+}  
+\end{funcproto}
 
 La funzione rimuove il semaforo indicato dall'argomento \param{name}, che
 prende un valore identico a quello usato per creare il semaforo stesso con
@@ -4592,23 +4735,23 @@ dovrà porre la variabile che contiene l'indirizzo del semaforo in un tratto di
 memoria che sia accessibile a tutti i processi in gioco.  La funzione che
 consente di inizializzare un semaforo anonimo è \funcd{sem\_init}, il cui
 prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{int sem\_init(sem\_t *sem, int pshared, unsigned int value)}
 
-  Inizializza il semaforo anonimo \param{sem}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà i valori:
-    \begin{errlist}
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fdecl{int sem\_init(sem\_t *sem, int pshared, unsigned int value)}
+\fdesc{Inizializza un semaforo anonimo.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
     \item[\errcode{EINVAL}] il valore di \param{value} eccede
       \const{SEM\_VALUE\_MAX}.
     \item[\errcode{ENOSYS}] il valore di \param{pshared} non è nullo ed il
       sistema non supporta i semafori per i processi.
-    \end{errlist}
-}
-\end{functions}
+  \end{errlist}
+}  
+\end{funcproto}
 
 La funzione inizializza un semaforo all'indirizzo puntato dall'argomento
 \param{sem}, e come per \func{sem\_open} consente di impostare un valore
@@ -4631,33 +4774,32 @@ potrà essere ottenuto direttamente sia con \func{shmget} (vedi
 sez.~\ref{sec:ipc_sysv_shm}) che con \func{shm\_open} (vedi
 sez.~\ref{sec:ipc_posix_shm}), oppure, nel caso che tutti i processi in gioco
 abbiano un genitore comune, con una mappatura anonima con \func{mmap} (vedi
-sez.~\ref{sec:file_memory_map}),\footnote{si ricordi che i tratti di memoria
-  condivisa vengono mantenuti nei processi figli attraverso la funzione
-  \func{fork}.} a cui essi poi potranno accedere.
+sez.~\ref{sec:file_memory_map}) a cui essi poi potranno accedere (si ricordi
+che i tratti di memoria condivisa vengono mantenuti nei processi figli
+attraverso la funzione \func{fork}).
 
 Una volta inizializzato il semaforo anonimo con \func{sem\_init} lo si potrà
 utilizzare nello stesso modo dei semafori normali con \func{sem\_wait} e
 \func{sem\_post}. Si tenga presente però che inizializzare due volte lo stesso
 semaforo può dar luogo ad un comportamento indefinito. 
 
-Una volta che non si intenda più utilizzare un semaforo anonimo questo può
-essere eliminato dal sistema; per far questo di deve utilizzare una apposita
+Qualora non si intenda più utilizzare un semaforo anonimo questo può essere
+eliminato dal sistema; per far questo di deve utilizzare una apposita
 funzione, \funcd{sem\_destroy}, il cui prototipo è:
-\begin{functions}
-  \headdecl{semaphore.h} 
-  
-  \funcdecl{int sem\_destroy(sem\_t *sem)}
 
-  Elimina il semaforo anonimo \param{sem}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
-    errore; nel quel caso \var{errno} assumerà i valori:
-    \begin{errlist}
-    \item[\errcode{EINVAL}] il valore di \param{value} eccede
-      \const{SEM\_VALUE\_MAX}.
-    \end{errlist}
+\begin{funcproto}{
+\fhead{semaphore.h}
+\fdecl{int sem\_destroy(sem\_t *sem)}
+\fdesc{Elimina un semaforo anonimo.}
 }
-\end{functions}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+    \item[\errcode{EINVAL}] l'argomento \param{sem} non indica un semaforo
+      valido.
+  \end{errlist}
+}  
+\end{funcproto}
 
 La funzione prende come unico argomento l'indirizzo di un semaforo che deve
 essere stato inizializzato con \func{sem\_init}; non deve quindi essere
@@ -4711,7 +4853,7 @@ segmento di memoria condivisa e del semaforo (il default scelto è
 Come prima istruzione (\texttt{\small 10}) si è provveduto ad installare un
 gestore di segnale che consentirà di effettuare le operazioni di pulizia
 (usando la funzione \func{Signal} illustrata in
-fig.~\ref{fig:sig_Signal_code}), dopo di che (\texttt{\small 10--16}) si è
+fig.~\ref{fig:sig_Signal_code}), dopo di che (\texttt{\small 12--16}) si è
 creato il segmento di memoria condivisa con la funzione \func{CreateShm} che
 abbiamo appena trattato in sez.~\ref{sec:ipc_posix_shm}, uscendo con un
 messaggio in caso di errore. 
@@ -4732,13 +4874,13 @@ permessi specificati dal terzo argomento, (indicante lettura e scrittura in
 notazione ottale). Infine il semaforo verrà inizializzato ad un valore nullo
 (il quarto argomento), corrispondete allo stato in cui risulta bloccato.
 
-A questo punto (\texttt{\small 23}) si potrà inizializzare il messaggio posto
+A questo punto (\texttt{\small 22}) si potrà inizializzare il messaggio posto
 nel segmento di memoria condivisa usando la stringa passata come argomento al
 programma. Essendo il semaforo stato creato già bloccato non ci si dovrà
 preoccupare di eventuali \itindex{race~condition} \textit{race condition}
 qualora il programma di modifica del messaggio venisse lanciato proprio in
 questo momento.  Una volta inizializzato il messaggio occorrerà però
-rilasciare il semaforo (\texttt{\small 25--28}) per consentirne l'uso; in
+rilasciare il semaforo (\texttt{\small 24--27}) per consentirne l'uso; in
 tutte queste operazioni si provvederà ad uscire dal programma con un opportuno
 messaggio in caso di errore.
 
@@ -4750,7 +4892,7 @@ controllo. Il primo passo (\texttt{\small 30--34}) è quello di acquisire (con
 semaforo ad inizio del ciclo; seguito (\texttt{\small 35--36}) dal tempo
 corrente.
 
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{\codesamplewidth}
     \includecodesample{listati/HandSigInt.c}
@@ -4762,14 +4904,14 @@ corrente.
 \end{figure}
 
 Prima della stampa del messaggio invece si deve acquisire il semaforo
-(\texttt{\small 31--34}) per evitare accessi concorrenti alla stringa da parte
+(\texttt{\small 30--33}) per evitare accessi concorrenti alla stringa da parte
 del programma di modifica. Una volta eseguita la stampa (\texttt{\small 41})
 il semaforo dovrà essere rilasciato (\texttt{\small 42--45}). Il passo finale
 (\texttt{\small 46}) è attendere per un secondo prima di eseguire da capo il
 ciclo. 
 
-Per uscire in maniera corretta dal programma sarà necessario interromperlo con
-il break da tastiera (\texttt{C-c}), che corrisponde all'invio del segnale
+Per uscire in maniera corretta dal programma sarà necessario fermarlo con una
+interruzione da tastiera (\texttt{C-c}), che corrisponde all'invio del segnale
 \signal{SIGINT}, per il quale si è installato (\texttt{\small 10}) una
 opportuna funzione di gestione, riportata in
 fig.~\ref{fig:ipc_posix_sem_shm_message_server_handler}. La funzione è molto
@@ -4777,7 +4919,7 @@ semplice e richiama le funzioni di rimozione sia per il segmento di memoria
 condivisa che per il semaforo, garantendo così che possa essere riaperto
 ex-novo senza errori in un futuro riutilizzo del comando.
 
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{\codesamplewidth}
     \includecodesample{listati/message_setter.c}
@@ -4933,11 +5075,12 @@ testo alla terminazione di quest'ultimo.
 % LocalWords:  process getvalue sval execve pshared ENOSYS heap PAGE destroy it
 % LocalWords:  xffffffff Arrays owner perms Queues used bytes messages device
 % LocalWords:  Cannot find such Segments getter Signal MSGMAXSIZE been stable
-% LocalWords:  for now it's break Berlin sources Let's an accidental feature
+% LocalWords:  for now it's break Berlin sources Let's an accidental feature fs
 % LocalWords:  Larry Wall Escape the Hell William ipctestid Identifier segment
 % LocalWords:  violation dell'I SIGINT setter Fri Dec Sleeping seconds ECHILD
 % LocalWords:  SysV capability short RESOURCE INFO UNDEFINED EFBIG semtimedop
-% LocalWords:  scan
+% LocalWords:  scan HUGETLB huge page NORESERVE copy RLIMIT MEMLOCK REMAP
+% LocalWords:  readmon Hierarchy defaults queues MSGQUEUE
 
 
 %%% Local Variables: