Materuale vario, correzioni e aggiornamenti sulla code di messaggi
[gapil.git] / ipc.tex
diff --git a/ipc.tex b/ipc.tex
index 520793d20023a7457032fe6a94bf03e261c7f1b1..48cc7b89ae2b35f627671433bce6fc2ff4b0027c 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,
@@ -690,9 +690,9 @@ stringa di richiesta dalla \textit{fifo} nota (che a questo punto si bloccherà
 tutte le volte che non ci sono richieste). Dopo di che, una volta terminata la
 stringa (\texttt{\small 40}) e selezionato (\texttt{\small 41}) un numero
 casuale per ricavare la frase da inviare, si procederà (\texttt{\small
-  42--46}) all'apertura della \textit{fifo} per la risposta, che poi
-\texttt{\small 47--48}) vi sarà scritta. Infine (\texttt{\small 49}) si chiude
-la \textit{fifo} di risposta che non serve più.
+  42--46}) all'apertura della \textit{fifo} per la risposta, che poi 
+(\texttt{\small 47--48}) vi sarà scritta. Infine (\texttt{\small 49}) si
+chiude la \textit{fifo} di risposta che non serve più.
 
 Il codice del client è invece riportato in fig.~\ref{fig:ipc_fifo_client},
 anche in questo caso si è omessa la gestione delle opzioni e la funzione che
@@ -1422,7 +1422,7 @@ file; il suo prototipo è:
     \var{msg\_qbytes} oltre il limite \const{MSGMNB} senza essere
     amministratore.
   \end{errlist}
-  ed inoltre \errval{EFAULT} ed \errval{EINVAL}  nel loro significato
+  ed inoltre \errval{EFAULT} ed \errval{EINVAL} nel loro significato
   generico.}
 \end{funcproto}
 
@@ -1839,7 +1839,6 @@ dei \ids{PID} da parte dei processi, un client eseguito in un momento
 successivo potrebbe ricevere un messaggio non indirizzato a lui.
 
 
-
 \subsection{I semafori}
 \label{sec:ipc_sysv_sem}
 
@@ -1974,7 +1973,6 @@ quanto riguarda gli altri campi invece:
   effettuata, viene inizializzato a zero.
 \end{itemize*}
 
-
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{.80\textwidth}
@@ -2079,10 +2077,9 @@ specificata con \param{cmd}, ed opera o sull'intero insieme specificato da
 \param{semid} o sul singolo semaforo di un insieme, specificato da
 \param{semnum}. 
 
-
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{.80\textwidth}
+  \begin{minipage}[c]{0.80\textwidth}
     \includestruct{listati/semun.h}
   \end{minipage} 
   \normalsize 
@@ -2318,7 +2315,7 @@ possa essere ripristinato all'uscita del processo.
 Infine \var{sem\_op} è il campo che controlla qual'è l'operazione che viene
 eseguita e determina in generale il comportamento della chiamata a
 \func{semop}. I casi possibili per il valore di questo campo sono tre:
-\begin{basedescript}{\desclabelwidth{2.0cm}}
+\begin{basedescript}{\desclabelwidth{1.8cm}}
 \item[\var{sem\_op} $>0$] In questo caso il valore viene aggiunto al valore
   corrente di \var{semval} per il semaforo indicato. Questa operazione non
   causa mai un blocco del processo, ed eventualmente \func{semop} ritorna
@@ -2410,7 +2407,7 @@ a queste strutture restano per compatibilità (in particolare con le vecchie
 versioni delle librerie del C, come le \acr{libc5}).
 
 \begin{figure}[!htb]
-  \centering \includegraphics[width=13cm]{img/semtruct}
+  \centering \includegraphics[width=12cm]{img/semtruct}
   \caption{Schema della struttura di un insieme di semafori.}
   \label{fig:ipc_sem_schema}
 \end{figure}
@@ -2605,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
@@ -2635,7 +2630,7 @@ norma, significa insieme a dei semafori.
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{\textwidth}
+  \begin{minipage}[c]{0.80\textwidth}
     \includestruct{listati/shmid_ds.h}
   \end{minipage} 
   \normalsize 
@@ -2652,7 +2647,7 @@ campo \var{shm\_perm} viene inizializzato come illustrato in
 sez.~\ref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte
 relativamente ai permessi di accesso; per quanto riguarda gli altri campi
 invece:
-\begin{itemize}
+\begin{itemize*}
 \item il campo \var{shm\_segsz}, che esprime la dimensione del segmento, viene
   inizializzato al valore di \param{size}.
 \item il campo \var{shm\_ctime}, che esprime il tempo di creazione del
@@ -2666,7 +2661,7 @@ invece:
   creato il segmento, viene inizializzato al \ids{PID} del processo chiamante.
 \item il campo \var{shm\_nattac}, che esprime il numero di processi agganciati
   al segmento viene inizializzato a zero.
-\end{itemize}
+\end{itemize*}
 
 Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti
 di memoria condivisa esistono una serie di limiti imposti dal sistema.  Alcuni
@@ -2786,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}
@@ -2833,7 +2828,6 @@ il suo prototipo è:
       per \param{shmaddr} o il valore \val{NULL} indicando \const{SHM\_REMAP}.
   \end{errlist}
   ed inoltre \errval{ENOMEM} nel suo significato generico.
-  
 }  
 \end{funcproto}
 
@@ -2906,14 +2900,14 @@ l'argomento  \param{shmaddr} non può essere nullo.
 
 In caso di successo la funzione \func{shmat} aggiorna anche i seguenti campi
 della struttura \struct{shmid\_ds}:
-\begin{itemize}
+\begin{itemize*}
 \item il tempo \var{shm\_atime} dell'ultima operazione di aggancio viene
   impostato al tempo corrente.
 \item il \ids{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
+\end{itemize*}
 
 Come accennato in sez.~\ref{sec:proc_fork} un segmento di memoria condivisa
 agganciato ad un processo viene ereditato da un figlio attraverso una
@@ -3347,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
@@ -3530,12 +3524,14 @@ 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.
+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
@@ -3599,66 +3595,64 @@ Data la assoluta genericità delle specifiche, il comportamento delle funzioni
 è subordinato in maniera quasi completa alla relativa implementazione, tanto
 che Stevens in \cite{UNP2} cita questo caso come un esempio della maniera
 standard usata dallo standard POSIX per consentire implementazioni non
-standardizzabili. Nel caso di Linux, 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.
+standardizzabili. 
+
+Nel caso di Linux, sia per quanto riguarda la memoria condivisa ed i semafori,
+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.\footnote{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{verbatim}
+\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{verbatim}
+\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,54 +3660,63 @@ 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 è:
-\begin{functions}
-  \headdecl{mqueue.h} 
-  
-  \funcdecl{mqd\_t mq\_open(const char *name, int oflag)}
-  
-  \funcdecl{mqd\_t mq\_open(const char *name, int oflag, unsigned long mode,
+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,
     struct mq\_attr *attr)}
-  
-  Apre una coda di messaggi POSIX impostandone le caratteristiche.
-  
-  \bodydesc{La funzione restituisce il descrittore associato alla coda in caso
-    di successo e -1 per un errore; nel quel caso \var{errno} assumerà i
-    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.
-    \end{errlist}
-    ed inoltre \errval{ENOMEM}, \errval{ENOSPC}, \errval{EFAULT},
-    \errval{EMFILE}, \errval{EINTR} ed \errval{ENFILE}.
+
+\fdesc{Apre una coda di messaggi POSIX impostandone le caratteristiche.}
 }
-\end{functions}
+
+{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 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{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}
 restituendo il descrittore ad essa associato, del tutto analogo ad un file
 descriptor, con l'unica differenza che lo standard prevede un apposito tipo
-\type{mqd\_t}.\footnote{nel caso di Linux si tratta in effetti proprio di un
-  normale 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.
+\type{mqd\_t}. Nel caso di Linux si tratta in effetti proprio di un normale
+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 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
@@ -3745,15 +3748,17 @@ 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
-  \begin{minipage}[c]{\textwidth}
+  \begin{minipage}[c]{0.90\textwidth}
     \includestruct{listati/mq_attr.h}
   \end{minipage} 
   \normalsize
@@ -3766,51 +3771,101 @@ 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 è:
-\begin{prototype}{mqueue.h}
-{int mq\_close(mqd\_t mqdes)}
 
-Chiude la coda \param{mqdes}.
-  
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 per un errore;
-  nel quel caso \var{errno} assumerà i valori \errval{EBADF} o
-  \errval{EINTR}.}
-\end{prototype}
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_close(mqd\_t mqdes)}
 
-La funzione è analoga a \func{close},\footnote{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.
+\fdesc{Chiude una coda di messaggi.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori \errval{EBADF} o \errval{EINTR} nel
+  loro significato generico.
+}  
+\end{funcproto}
 
+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 è:
-\begin{prototype}{mqueue.h}
-{int mq\_unlink(const char *name)}
+funzione di sistema \funcd{mq\_unlink}, il cui prototipo è:
 
-Rimuove una coda di messaggi.
-  
-\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}
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_unlink(const char *name)}
+
+\fdesc{Rimuove una coda di messaggi.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  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,\footnote{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
@@ -3820,141 +3875,163 @@ 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.
 
 Come accennato ad ogni coda di messaggi è associata una struttura
 \struct{mq\_attr}, che può essere letta e modificata attraverso le due
 funzioni \funcd{mq\_getattr} e \funcd{mq\_setattr}, i cui prototipi sono:
-\begin{functions}
-  \headdecl{mqueue.h} 
-  
-  \funcdecl{int mq\_getattr(mqd\_t mqdes, struct mq\_attr *mqstat)}
-  Legge gli attributi di una coda di messaggi POSIX.
-  
-  \funcdecl{int mq\_setattr(mqd\_t mqdes, const struct mq\_attr *mqstat,
+
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_getattr(mqd\_t mqdes, struct mq\_attr *mqstat)}
+\fdesc{Legge gli attributi di una coda di messaggi POSIX.}
+\fdecl{int mq\_setattr(mqd\_t mqdes, const struct mq\_attr *mqstat,
     struct mq\_attr *omqstat)}
-  Modifica gli attributi di una coda di messaggi POSIX.
-  
-  \bodydesc{Entrambe le funzioni restituiscono 0 in caso di successo e -1 in
-    caso di errore; nel quel caso \var{errno} assumerà i valori \errval{EBADF}
-    o \errval{EINVAL}.}
-\end{functions}
+\fdesc{Modifica gli attributi di una coda di messaggi POSIX.}
+}
+
+{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:
-\begin{functions}
-  \headdecl{mqueue.h} 
-  
-  \funcdecl{int mq\_send(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len,
-    unsigned int msg\_prio)} 
-  Esegue l'inserimento di un messaggio su una coda.
-  
-  \funcdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t
-    msg\_len, unsigned msg\_prio, const struct timespec *abs\_timeout)}   
-  Esegue l'inserimento di un messaggio su una coda entro il tempo
-  \param{abs\_timeout}.
+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:
 
-  
-  \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ per un
-    errore; nel quel caso \var{errno} assumerà i valori:
-    \begin{errlist}
+\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 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}
+}
+
+{Entrambe le funzioni ritornano $0$ 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 è 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.
-    \end{errlist}    
-    ed inoltre \errval{EBADF}, \errval{ENOMEM} ed \errval{EINTR}.}
-\end{functions}
+      effettuato entro il tempo stabilito (solo \func{mq\_timedsend}).
+  \end{errlist}
+  ed inoltre \errval{EBADF}, \errval{EINTR} nel suo 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 comunque
+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}
+  \end{errlist}
+  ed inoltre \errval{EBADF} o \errval{EINTR} nel loro significato generico.  }
+\end{funcproto}
 
-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.}
+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
@@ -3975,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
@@ -3996,39 +4071,48 @@ 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
@@ -4042,12 +4126,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
@@ -4062,8 +4146,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
@@ -4074,13 +4158,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}
@@ -4093,18 +4176,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
@@ -4398,7 +4482,7 @@ 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.
+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
@@ -4927,11 +5011,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: