+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 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 è piena.
+ \item[\errcode{EMSGSIZE}] La lunghezza del messaggio \param{msg\_len}
+ eccede il limite impostato per la coda.
+ \item[\errcode{ENOMEM}] Il kernel non ha memoria sufficiente. Questo
+ errore può avvenire quando l'inserimento del messaggio
+ \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} 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, 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}, ritorna comunque con un errore di \errcode{ETIMEDOUT}.
+
+
+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.
+
+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\_getaddr} 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}. Qualora non
+interessi usare la priorità dei messaggi si
+
+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 \figref{fig:file_sigevent}) introdotta dallo
+standard POSIX.1b per gestire la notifica di eventi; per altri dettagli si può
+vedere quanto detto in \secref{sec:file_asyncronous_io} a proposito dell'uso
+della stessa struttura per l'invio dei segnali usati per l'I/O asincrono.
+
+Attraverso questa struttura si possono impostare le modalità con cui viene
+effettuata la notifica; in particolare il campo \var{sigev\_notify} deve
+essere posto a \const{SIGEV\_SIGNAL}\footnote{il meccanismo di notifica basato
+ sui thread, specificato tramite il valore \const{SIGEV\_THREAD}, non è
+ implementato.} ed il campo \var{sigev\_signo} deve indicare il valore del
+segnale che sarà inviato al processo. Inoltre il campo \var{sigev\_value} è il
+puntatore ad una struttura \struct{sigval\_t} (definita in
+\figref{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 \secref{sec:sig_real_time} a proposito dei segnali
+ real-time.} posto che questo sia installato nella forma estesa vista in
+\secref{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. 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
+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
+\figref{fig:sig_siginfo_t}). In particolare \var{si\_pid} viene impostato al
+valore del \acr{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 \secref{sec:sig_sigaction} e \secref{sec:sig_real_time}.}
+