+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.
+
+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.}
+
+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}
+mqueue /dev/mqueue mqueue defaults 0 0
+\end{verbatim}
+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
+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,
+ 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}.
+}
+\end{functions}
+
+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.
+
+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:
+\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
+ \func{mq\_send}.
+\item[\const{O\_WRONLY}] Apre la coda solo per la trasmissione di messaggi. Il
+ processo potrà usare il descrittore con \func{mq\_send} ma non con
+ \func{mq\_receive}.
+\item[\const{O\_RDWR}] Apre la coda solo sia per la trasmissione che per la
+ ricezione.
+\item[\const{O\_CREAT}] Necessario qualora si debba creare la coda; la
+ presenza di questo bit richiede la presenza degli ulteriori argomenti
+ \param{mode} e \param{attr}.
+\item[\const{O\_EXCL}] Se usato insieme a \const{O\_CREAT} fa fallire la
+ chiamata se la coda esiste già, altrimenti esegue la creazione atomicamente.
+\item[\const{O\_NONBLOCK}] Imposta la coda in modalità non bloccante, le
+ funzioni di ricezione e trasmissione non si bloccano quando non ci sono le
+ risorse richieste, ma ritornano immediatamente con un errore di
+ \errcode{EAGAIN}.
+\end{basedescript}
+
+I primi tre bit specificano la modalità di apertura della coda, e sono fra
+loro esclusivi. Ma qualunque sia la modalità in cui si è aperta una coda,
+questa potrà essere riaperta più volte in una modalità diversa, e vi si potrà
+sempre accedere attraverso descrittori diversi, esattamente come si può fare
+per i file normali.
+
+Se la coda non esiste e la si vuole creare si deve specificare
+\const{O\_CREAT}, in tal caso occorre anche specificare i permessi di
+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}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{\textwidth}
+ \includestruct{listati/mq_attr.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{mq\_attr}, contenente gli attributi di una
+ coda di messaggi POSIX.}
+ \label{fig:ipc_mq_attr}
+\end{figure}
+
+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.
+
+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}
+
+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.
+
+
+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)}
+
+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}
+
+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.
+
+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
+annulla. Pertanto anche dopo aver eseguito con successo \func{mq\_unlink} la
+coda resterà accessibile a tutti i processi che hanno un descrittore aperto su
+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
+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,
+ 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}
+
+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.
+
+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}.
+
+
+ \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ per un
+ errore; nel quel caso \var{errno} assumerà i 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{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{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}
+
+Entrambe le funzioni richiedono un puntatore al testo del messaggio
+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.
+
+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.
+
+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}
+ \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{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.}
+
+Se la dimensione specificata da \param{msg\_len} non è sufficiente a contenere
+il messaggio, entrambe le funzioni, al contrario di quanto avveniva nelle code
+di messaggi di SysV, ritornano un errore di \errcode{EMSGSIZE} senza estrarre
+il messaggio. È pertanto opportuno eseguire sempre una chiamata a
+\func{mq\_getattr} prima di eseguire una ricezione, in modo da ottenere la
+dimensione massima dei messaggi sulla coda, per poter essere in grado di
+allocare dei buffer sufficientemente ampi per la lettura.
+
+Se si specifica un puntatore per l'argomento \param{msg\_prio} il valore della
+priorità del messaggio viene memorizzato all'indirizzo da esso indicato.
+Qualora non interessi usare la priorità dei messaggi si può specificare
+\var{NULL}, ed usare un valore nullo della priorità nelle chiamate a
+\func{mq\_send}.
+
+Si noti che con le code di messaggi POSIX non si ha la possibilità di
+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
+differenza fra le due funzioni è che la seconda non attende indefinitamente e
+passato il tempo massimo \param{abs\_timeout} ritorna comunque con un errore
+di \errcode{ETIMEDOUT}.
+
+Uno dei problemi sottolineati da Stevens in \cite{UNP2}, comuni ad entrambe le
+tipologie di code messaggi, è che non è possibile per chi riceve identificare
+chi è che ha inviato il messaggio, in particolare non è possibile sapere da
+quale utente esso provenga. Infatti, in mancanza di un meccanismo interno al
+kernel, anche se si possono inserire delle informazioni nel messaggio, queste
+non possono essere credute, essendo completamente dipendenti da chi lo invia.
+Vedremo però come, attraverso l'uso del meccanismo di notifica, sia possibile
+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.
+ \item[\errcode{EBADF}] il descrittore non fa riferimento ad una coda di
+ messaggi.
+ \end{errlist}}
+\end{prototype}
+
+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.
+
+Il comportamento di \func{mq\_notify} dipende dal valore dell'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
+\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
+\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
+fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore del segnale
+un valore numerico o un indirizzo,\footnote{per il suo uso si riveda la
+ trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei segnali
+ \textit{real-time}.} posto che questo sia installato nella forma estesa
+vista in sez.~\ref{sec:sig_sigaction}.
+
+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.
+
+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
+bloccato in una chiamata a \func{mq\_receive}, in questo caso infatti il
+processo bloccato ha la precedenza ed il messaggio gli viene immediatamente
+inviato, mentre per il meccanismo di notifica tutto funziona come se la coda
+fosse rimasta vuota.
+
+Quando un messaggio arriva su una coda vuota al processo che si era registrato
+viene inviato il segnale specificato da \code{notification->sigev\_signo}, e
+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
+\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
+occorre per ripetere la richiesta di notifica basta avere cura di eseguire
+questa operazione prima di estrarre i messaggi presenti dalla coda.
+
+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}.}
+
+
+
+\subsection{Memoria condivisa}
+\label{sec:ipc_posix_shm}
+
+La memoria condivisa è stato il primo degli oggetti di IPC POSIX inserito nel
+kernel ufficiale; il supporto a questo tipo di oggetti è realizzato attraverso
+il filesystem \texttt{tmpfs}, uno speciale filesystem che mantiene tutti i
+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}
+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}
+mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs
+\end{verbatim}
+
+Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e
+\texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne
+la titolarità, e \texttt{nr\_blocks} che permette di specificarne la
+dimensione in blocchi, cioè in multipli di \const{PAGECACHE\_SIZE} che in
+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)}
+
+ 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
+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
+ comporta, da parte delle funzioni di libreria, il tentativo di accedere a
+ \file{/dev/shm/dev/shm/nome}.}
+
+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 comprendente almeno uno dei due valori \const{O\_RDONLY} e
+\const{O\_RDWR}; i valori possibili per i vari bit sono quelli visti in
+sez.~\ref{sec:file_open_close} dei quali però \func{shm\_open} riconosce solo
+i seguenti:
+\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{O\_RDONLY}] Apre il file descriptor associato al segmento di
+ memoria condivisa per l'accesso in sola lettura.
+\item[\const{O\_RDWR}] Apre il file descriptor associato al segmento di
+ memoria condivisa per l'accesso in lettura e scrittura.
+\item[\const{O\_CREAT}] Necessario qualora si debba creare il segmento di
+ memoria condivisa se esso non esiste; in questo caso viene usato il valore
+ di \param{mode} per impostare i permessi, che devono essere compatibili con
+ le modalità con cui si è aperto il file.
+\item[\const{O\_EXCL}] Se usato insieme a \const{O\_CREAT} fa fallire la
+ chiamata a \func{shm\_open} se il segmento esiste già, altrimenti esegue la
+ creazione atomicamente.
+\item[\const{O\_TRUNC}] Se il segmento di memoria condivisa esiste già, ne
+ tronca le dimensioni a 0 byte.
+\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
+\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}
+
+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
+descriptor precedentemente aperti con \func{shm\_open}, né sui segmenti già
+mappati in memoria; questi verranno cancellati automaticamente dal sistema
+solo con le rispettive chiamate a \func{close} e \func{munmap}. Una volta
+eseguita questa funzione però, qualora si richieda l'apertura di un segmento
+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]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/MemShared.c}
+ \end{minipage}
+ \normalsize
+ \caption{Il codice delle funzioni di gestione dei segmenti di memoria
+ condivisa POSIX.}
+ \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.
+
+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.
+
+La terza funzione (\texttt{\small 40--45}) è \func{RemoveShm}, e serve a
+cancellare un segmento di memoria condivisa. Dato che al contrario di quanto
+avveniva con i segmenti del \textit{SysV-IPC} gli oggetti allocati nel kernel
+vengono rilasciati automaticamente quando nessuna li usa più, tutto quello che
+c'è da fare (\texttt{\small 44}) in questo caso è chiamare \func{shm\_unlink},
+restituendo al chiamante il valore di ritorno.
+
+
+