+messaggi. Le code di messaggi sono oggetti analoghi alle pipe o alle fifo,
+anche se la loro struttura è diversa. La funzione che permette di ottenerne
+una è \func{msgget} ed il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{int msgget(key\_t key, int flag)}
+
+ Restituisce l'identificatore di una cosa di messaggi.
+
+ \bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
+ in caso di errore, nel qual caso \var{errno} viene settato ad uno dei
+ valori:
+ \begin{errlist}
+ \item[\macro{EACCES}] Il processo chiamante non ha i privilegi per accedere
+ alla coda richiesta.
+ \item[\macro{EEXIST}] Si è richiesta la creazione di una coda che già
+ esiste, ma erano specificati sia \macro{IPC\_CREAT} che \macro{IPC\_EXCL}.
+ \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+ \item[\macro{ENOENT}] Si è cercato di ottenere l'identificatore di una coda
+ di messaggi specificando una chiave che non esiste e \macro{IPC\_CREAT}
+ non era specificato.
+ \item[\macro{ENOSPC}] Si è cercato di creare una coda di messaggi quando è
+ stato il limite massimo del sistema.
+ \end{errlist}
+ ed inoltre \macro{ENOMEM}.
+}
+\end{functions}
+
+Le funzione (come le analoghe che si usano per gli altri oggetti) serve sia a
+ottenere l'identificatore di una coda di messaggi esistente, che a crearne una
+nuova. L'argomento \param{key} specifica la chiave che è associata
+all'oggetto, eccetto il caso in cui si specifichi il valore
+\macro{IPC\_PRIVATE}, nel qual caso la coda è creata ex-novo e non vi è
+associata alcuna chiave, il processo (ed i suoi eventuali figli) potranno
+farvi riferimento solo attraverso l'identificatore.
+
+Se invece si specifica un valore diverso da \macro{IPC\_PRIVATE}\footnote{in
+ Linux questo significa un valore diverso da zero.} l'effetto della funzione
+dipende dal valore di \param{flag}, se questo è nullo la funzione si limita ad
+effettuare una ricerca sugli oggetti esistenti, restituendo l'identificatore
+se trova una corrispondenza, o fallendo con un errore di \macro{ENOENT} se non
+esiste o di \macro{EACCESS} se si sono specificati dei permessi non validi.
+
+Se invece si vuole creare una nuova coda di messaggi \param{flag} non può
+essere nullo e deve essere fornito come maschera binaria, impostando il bit
+corrispondente al valore \macro{IPC\_CREAT}. In questo caso i nove bit meno
+significativi di \param{flag} saranno usati come permessi per il nuovo
+oggetto, secondo quanto illustrato in \secref{sec:ipc_sysv_access_control}.
+Se si imposta anche il bit corrispondente a \macro{IPC\_EXCL} la funzione avrà
+successo solo se l'oggetto non esiste già, fallendo con un errore di
+\macro{EEXIST} altrimenti.
+
+Si tenga conto che l'uso di \macro{IPC\_PRIVATE} non impedisce ad altri
+processi di accedere alla coda (se hanno privilegi sufficienti) una volta che
+questi possano indovinare o ricavare (ad esempio per tentativi)
+l'identificatore ad essa associato. Per come sono implementati gli oggetti di
+IPC infatti non esiste una maniera che garantisca l'accesso esclusivo ad una
+coda di messaggi. Usare \macro{IPC\_PRIVATE} o macro{IPC\_CREAT} e
+\macro{IPC\_EXCL} per \param{flag} comporta solo la creazione di una nuova
+coda.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|c|r|l|l|}
+ \hline
+ \textbf{Costante} & \textbf{Valore} & \textbf{File in \texttt{proc}}
+ & \textbf{Significato} \\
+ \hline
+ \hline
+ \macro{MSGMNI}& 16& \file{msgmni} & Numero massimo di code di
+ messaggi. \\
+ \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
+ messaggio.\\
+ \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima di una coda di
+ messaggi.\\
+ \hline
+ \end{tabular}
+ \caption{Valori delle costanti associati ai limiti delle code di messaggi.}
+ \label{tab:ipc_msg_limits}
+\end{table}
+
+Le code di messaggi sono caratterizzate da tre limiti fondamentali, definiti
+negli header e corrispondenti alle prime tre costanti riportate in
+\tabref{tab:ipc_msg_limits}, come accennato però in Linux è possibile
+modificare questi limiti attraverso l'uso di \func{syscntl} o scrivendo nei
+file \file{msgmax}, \file{msgmnb} e \file{msgmni} di \file{/proc/sys/kernel/}.
+
+
+\begin{figure}[htb]
+ \centering \includegraphics[width=15cm]{img/mqstruct}
+ \caption{Schema della struttura di una coda messaggi.}
+ \label{fig:ipc_mq_schema}
+\end{figure}
+
+
+Una coda di messaggi è costituita da una \textit{linked list};\footnote{una
+ \textit{linked list} è una tipica struttura di dati, organizzati in una
+ lista in cui ciascun elemento contiene un puntatore al successivo. In questo
+ modo la struttura è veloce nell'estrazione ed immissione dei dati dalle
+ estremità dalla lista (basta aggiungere un elemento in testa o in coda ed
+ aggiornare un puntatore), e relativamente veloce da attraversare in ordine
+ sequenziale (seguendo i puntatori), è invece relativamente lenta
+ nell'accesso casuale e nella ricerca.} i nuovi messaggi vengono inseriti in
+coda alla lista e vengono letti dalla cima, in \figref{fig:ipc_mq_schema} si è
+riportato lo schema con cui queste strutture vengono mantenute dal
+kernel.\footnote{lo schema illustrato in figura è in realtà una semplificazione
+ di quanto usato fino ai kernel della serie 2.2.x, nei kernel della serie
+ 2.4.x la gestione è effettuata in maniera diversa; ma esso illustra comunque
+ in maniera adeguata i principi di funzionamento delle code di messaggi.}
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}
+struct msqid_ds {
+ struct ipc_perm msg_perm; /* structure for operation permission */
+ time_t msg_stime; /* time of last msgsnd command */
+ time_t msg_rtime; /* time of last msgrcv command */
+ time_t msg_ctime; /* time of last change */
+ msgqnum_t msg_qnum; /* number of messages currently on queue */
+ msglen_t msg_qbytes; /* max number of bytes allowed on queue */
+ pid_t msg_lspid; /* pid of last msgsnd() */
+ pid_t msg_lrpid; /* pid of last msgrcv() */
+ struct msg *msg_first; /* first message on queue, unused */
+ struct msg *msg_last; /* last message in queue, unused */
+ unsigned long int msg_cbytes; /* current number of bytes on queue */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{msgid\_ds}, associata a ciascuna coda di
+ messaggi.}
+ \label{fig:ipc_msgid_sd}
+\end{figure}
+
+A ciascuna coda è associata una struttura \var{msgid\_ds}, la cui definizione
+è riportata in \secref{fig:ipc_msgid_sd}, il significato dei vari campi è
+riportato nella figura. In questa struttura il kernel\footnote{come accennato
+ questo vale fino ai kernel della serie 2.2.x, essa viene usata nei kernel
+ della serie 2.4.x solo per compatibilità in quanto è quella restituita dalle
+ funzioni dell'interfaccia. In \figref{fig:ipc_msgid_sd} sono elencati i
+ campi significativi definiti in \file{sys/msg.h}, a cui si sono agguinti gli
+ ultimi tre campi che sono previsti dalla implementazione originale di System
+ V, ma non dallo standard Unix98.} mantiene le principali informazioni
+riguardo lo stato corrente della coda. Quando si crea una nuova coda con
+\func{msgget} questa struttura viene inizializzata, in particolare il campo
+\var{msg\_perm} viene inizializzato come illustrato in
+\secref{sec:ipc_sysv_access_control}, per quanto riguarda gli altri campi
+invece:
+\begin{itemize}
+\item il campo \var{msg\_qnum}, che esprime il numero di messaggi presenti
+ sulla coda, viene inizializzato a 0.
+\item i campi \var{msg\_lspid} e \var{msg\_lrpid}, che esprimono
+ rispettivamente il \acr{pid} dell'ultimo processo che ha inviato o ricevuto
+ un messaggio sulla coda, sono inizializzati a 0.
+\item i campi \var{msg\_stime} e \var{msg\_rtime}, che esprimono
+ rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
+ messaggio sulla coda, sono inizializzati a 0.
+\item il campo \var{msg\_ctime} viene inizializzato al tempo corrente.
+\item il campo \var{msg\_qbytes} viene inizializzati al limite di sistema.
+\item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
+ primo e ultimo messagio sono inizializzati a \macro{NULL} e
+ \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
+ inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
+ e non devono essere utilizzati da programmi in user space).
+\end{itemize}
+
+Una volta creata una coda di messaggi le operazioni di controllo vengono
+effettuate con la funzione \func{msgctl}, che (come le analoghe \func{semctl}
+e \func{shmctl}) fa le veci di quello che \func{ioctl} è per i file; il suo
+prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{int msgctl(int msqid, int cmd, struct msqid\_ds *buf)}
+
+ Esegue l'operazione specificata da \param{cmd} sulla coda \param{msqid}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di
+ errore, nel qual caso \var{errno} viene settato a:
+ \begin{errlist}
+ \item[\macro{EACCES}] Si è richiesto \macro{IPC\_STAT} ma processo chiamante
+ non ha i privilegi di lettura sulla coda.
+ \item[\macro{EIDRM}] La coda richiesta è marcata per essere cancellata.
+ \item[\macro{EPERM}] Si è richiesto \macro{IPC\_SET} o \macro{IPC\_RMID} ma
+ il processo non ha i privilegi, o si è richiesto di aumentare il valore di
+ \var{msg\_qbytes} oltre il limite \macro{MSGMNB} senza essere
+ amministratore.
+ \end{errlist}
+ ed inoltre \macro{EFAULT} ed \macro{EINVAL}.
+}
+\end{functions}
+
+La funzione permette di accedere ai valori della struttura \var{msqid\_ds},
+mantenuta all'indirizzo \param{buf}, per la coda specificata
+dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
+valore dell'argomento \param{cmd}, che specifica il tipo di azione da
+eseguire; i valori possibili sono:
+\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}}
+\item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
+ struttura indicata da \param{buf}. Occorre avere il permesso di lettura
+ sulla coda.
+\item[\macro{IPC\_RMID}] Rimuove la coda, cancellando tutti i dati, con
+ effetto immediato. Tutti i processi che cercheranno di accedere alla coda
+ riceveranno un errore di \macro{EIDRM}, e tutti processi in attesa su
+ funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo
+ il medesimo errore. Questo comando può essere eseguito solo da un processo
+ con userid effettivo corrispondente al creatore a o al proprietario della
+ coda, o all'amministratore.
+\item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+ della coda, ed il limite massimo sulle dimensioni del totale dei messaggi in
+ essa contenuti (\var{msg\_qbytes}). I valori devono essere passati in una
+ struttura \var{msqid\_ds} puntata da \param{buf}. Per modificare i valori
+ di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid} occorre
+ essere il proprietario o il creatore della coda, oppure l'amministratore; lo
+ stesso vale per \var{msg\_qbytes}, con la restrizione che solo
+ l'amministratore può incrementarne il valore a limiti superiori a
+ \macro{MSGMNB}.
+\end{basedescript}
+
+
+Una volta che si abbia a disposizione l'identificatore, per inviare un
+messaggio su una coda si utilizza la funzione \func{msgsnd}; il suo prototipo
+è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{int msgsnd(int msqid, struct msgbuf *msgp, size\_t msgsz, int
+ msgflg)}
+
+ Invia un messaggio sulla coda \param{msqid}.
+
+ \bodydesc{La funzione restituisce 0, e -1 in caso di errore, nel qual caso
+ \var{errno} viene settata a:
+ \begin{errlist}
+ \item[\macro{EACCES}] Non si hanno i privilegi di accesso sulla coda.
+ \item[\macro{EIDRM}] La coda è stata cancellata.
+ \item[\macro{EAGAIN}] Il messaggio non può essere inviato perché si è
+ superato il limite \var{msg\_qbytes} sul numero massimo di byte presenti
+ sulla coda, e si è richiesto \macro{IPC\_NOWAIT} in \param{flag}.
+ \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
+ \item[\macro{EINVAL}] Si è specificato un \param{msgid} invalido, o un
+ valore non positivo per \param{mtype}, o un valore di \param{msgsz}
+ maggiore di \macro{MSGMAX}.
+ \end{errlist}
+ ed inoltre \macro{EFAULT} ed \macro{ENOMEM}.
+}
+\end{functions}
+
+La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
+messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso
+l'argomento \param{msgp}. Quest'ultimo deve venire passato sempre in una
+forma che corrisponda alla struttura \var{msgbuf} riportata in
+\figref{fig:ipc_msbug}. La struttura è solo un modello, la sola cosa che
+conta è abbia come primo membro un campo \var{mtype}, come nell'esempio; esso
+infatti serve ad identificare il tipo di messaggio e deve essere sempre
+specificato come intero positivo. Il campo \var{mtext} invece può essere di
+qualsiasi tipo e dimensione, e deve contenere il testo del messaggio.
+
+In generale pertanto occorrerà ridefinire una struttura analoga a quella di
+\figref{fig:ipc_msbug}, adattando alle proprie esigenze il campo \var{mtype},
+e avendo cura di mantenere come primo campo un valore di tipo \ctyp{long}. Il
+resto della struttura andrà a costituire il corpo del messaggio, la cui
+dimensione deve essere specificata sempre attraverso \param{msgsz}. Si tenga
+presente che la lunghezza che deve essere indicata in questo argomento è solo
+quella del messaggio, non di tutta la struttura, se cioè \var{message} è la
+struttura che si passa alla funzione, \param{msgsz} dovrà essere uguale a
+\code{sizeof(message)-sizeof(long)} (se consideriamo il caso dell'esempio in
+\figref{fig:ipc_msbug} \param{msgsz} dovrà essere pari a \macro{LENGHT}).
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}
+ struct msgbuf {
+ long mtype; /* message type, must be > 0 */
+ char mtext[LENGTH]; /* message data */
+ };
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Schema della struttura \var{msgbug}, da utilizzare come argomento
+ per inviare/ricevere messaggi.}
+ \label{fig:ipc_msbug}
+\end{figure}
+
+Per capire meglio il funzionamento della funzione riprendiamo in
+considerazione la struttura della coda illustrata in
+\secref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio
+sarà aggiunto in fondo alla lista inserendo una nuova struttura \var{msg}, il
+puntatore \var{msg\_last} di \var{msqid\_ds} verrà aggiornato, come pure il
+puntatore al messaggio successivo per quello che era il precedente ultimo
+messaggio; il valore di \var{mtype} verrà mantenuto in \var{msg\_type} ed il
+valore di \param{msgsz} in \var{msg\_ts}; il testo del messaggio sarà copiato
+all'indirizzo specificato da \var{msg\_spot}.
+
+Il valore dell'argomento \param{flag} permette di specificare il comportamento
+della funzione. Di norma, quando si specifica un valore nullo, la funzione
+ritorna immediatamente a meno che si sia ecceduto il valore di
+\var{msg\_qbytes}, o il limite di sistema sul numero di messaggi, nel qual
+caso si blocca mandando il processo in stato di \textit{sleep}. Se si
+specifica per \param{flag} il valore \macro{IPC\_NOWAIT} la funzione opera in
+modalità non bloccante, ed in questi casi ritorna immediatamente con un errore
+di \macro{EAGAIN}.
+
+Se non si specifica \macro{IPC\_NOWAIT} la funzione resterà bloccata fintanto
+che non si liberano risorse sufficienti per poter inserire nella coda il
+messaggio, nel qual caso ritornerà normalmente. La funzione può ritornare, con
+una condizione di errore anche in due altri casi: quando la coda viene rimossa
+(nel qual caso si ha un errore di \macro{EIDRM}) o quando la funzione viene
+interrotta da un segnale (nel qual caso si ha un errore di \macro{EINTR}).
+
+Una volta completato con successo l'invio del messaggio sulla coda, la
+funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
+modificati:
+\begin{itemize}
+\item Il valore di \var{msg\_lspid}, che viene impostato al \acr{pid} del
+ processo chiamante.
+\item Il valore di \var{msg\_qnum}, che viene incrementato di uno.
+\item Il valore \var{msg\_stime}, che viene impostato al tempo corrente.
+\end{itemize}
+
+
+La funzione che permette di estrarre da una coda un messaggio (che sarà
+rimosso dalla stessa) è \func{msgrcv}; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/msg.h}
+
+ \funcdecl{ssize\_t msgrcv(int msqid, struct msgbuf *msgp, size\_t msgsz,
+ long msgtyp, int msgflg)}
+
+ Legge un messaggio dalla coda \param{msqid}.
+
+ \bodydesc{La funzione restituisce il numero di byte letti in caso di
+ successo, e -1 in caso di errore, nel qual caso \var{errno} viene settata
+ a:
+ \begin{errlist}
+ \item[\macro{EACCES}] Non si hanno i privilegi di accesso sulla coda.
+ \item[\macro{EIDRM}] La coda è stata cancellata.
+ \item[\macro{E2BIG}] Il testo del messaggio è più lungo di \param{msgsz} e
+ non si è specificato \macro{MSG\_NOERROR} in \param{msgflg}.
+ \item[\macro{EINTR}] La funzione è stata interrotta da un segnale mentre era
+ in attesa di ricevere un messaggio.
+ \item[\macro{EINVAL}] Si è specificato un \param{msgid} invalido o un valore
+ di \param{msgsz} negativo.
+ \end{errlist}
+ ed inoltre \macro{EFAULT}.
+}
+\end{functions}
+
+La funzione permette di estrarre un messaggio dalla coda e di scriverlo nel
+buffer indicato da \param{msgp}, che deve puntare ad una struttura della forma
+mostrata in \figref{fig:ipc_msbug}. L'argomento \param{msgsz} indica la
+lunghezza massima del testo del messaggio (equivalente al valore del parametro
+\macro{LENGHT} nell'esempio di \figref{fig:ipc_msbug}).
+
+Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene
+rimosso dalla coda, in caso contrario se \param{msgflg} è impostato a
+\macro{MSG\_NOERROR} il messaggio viene troncato e la parte in eccesso viene
+perduta, altrimenti il messaggio non viene estratto e la funzione ritorna con
+un errore di \macro{E2BIG}.
+
+L'argomento \param{msgtyp} permette di restringere la ricerca ad un
+sottoinsieme dei messaggi presenti sulla coda; in particolare:
+\begin{itemize}
+\item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè
+ quello fra i presenti che è stato inserito inserito per primo.
+\item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui
+ tipo (il valore del campo \var{mtype}) corrisponde a quanto specificato.
+\item se \param{msgtyp} è negativo viene estratto il primo messaggio nella coda
+ con il tipo più basso, fra quelli di tipo inferiore al valore assoluto di
+ quanto specificato.
+\end{itemize}
+
+Il valore di \param{msgflg} permette di controllare il comportamento della
+funzione, esso può assumere valore nullo o essere specificato come maschera
+binaria di uno o più dei valori. Oltre al precedente \macro{MSG\_NOERROR}, si
+può impostare il valore \macro{MSG\_EXCEPT}, che quando \param{msgtyp} è
+positivo permette di leggere il primo messaggio nella coda con tipo diverso da
+\param{msgtyp}, ed il valore \macro{IPC\_NOWAIT} che causa il ritorno
+immediato della funzione quando non ci sono messaggi sulla coda.
+
+Il comportamento usuale della funzione infatti, quando non ci sono messaggi
+disponibili per la lettura, è di bloccare il processo in stato di
+\textit{sleep}; nel caso però si sia specificato \macro{IPC\_NOWAIT} la
+funzione ritorna immediatamente con un errore \macro{ENOMSG}. Altrimenti la
+funzione ritorna normalmente non appena viene inserito un messaggio del tipo
+desiderato, oppure ritorna con errore qualora la cosa sia rimossa (con un
+\macro{EIDRM}) o se il processo viene interrotto da un segnale (con un
+\macro{EINTR}).
+
+Una volta completata con successo l'estrazione del messaggio dalla coda, la
+funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
+modificati:
+\begin{itemize}
+\item Il valore di \var{msg\_lrpid}, che viene impostato al \acr{pid} del
+ processo chiamante.
+\item Il valore di \var{msg\_qnum}, che viene decrementato di uno.
+\item Il valore \var{msg\_rtime}, che viene impostato al tempo corrente.
+\end{itemize}
+
+
+