+Il terzo oggetto introdotto dal \textit{SysV-IPC} è quello dei segmenti di
+memoria condivisa. La funzione di sistema che permette di ottenerne uno è
+\funcd{shmget}, ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/ipc.h}
+\fhead{sys/shm.h}
+\fdecl{int shmget(key\_t key, int size, int flag)}
+\fdesc{Ottiene o crea una memoria condivisa.}
+}
+
+{La funzione ritorna l'identificatore (un intero positivo) in caso di successo
+ e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{ENOSPC}] si è superato il limite (\const{SHMMNI}) sul numero
+ di segmenti di memoria nel sistema, o cercato di allocare un segmento le
+ cui dimensioni fanno superare il limite di sistema (\const{SHMALL}) per
+ la memoria ad essi riservata.
+ \item[\errcode{EINVAL}] si è richiesta una dimensione per un nuovo segmento
+ maggiore di \const{SHMMAX} o minore di \const{SHMMIN}, o se il segmento
+ già esiste \param{size} è maggiore delle sue dimensioni.
+ \item[\errcode{ENOMEM}] il sistema non ha abbastanza memoria per poter
+ contenere le strutture per un nuovo segmento di memoria condivisa.
+ \item[\errcode{ENOMEM}] si è specificato \const{IPC\_HUGETLB} ma non si
+ hanno i privilegi di amministratore.
+ \end{errlist}
+ ed inoltre \errval{EACCES}, \errval{ENOENT}, \errval{EEXIST},
+ \errval{EIDRM}, con lo stesso significato che hanno per \func{msgget}.}
+\end{funcproto}
+
+
+La funzione, come \func{semget}, è analoga a \func{msgget}, ed identico è
+l'uso degli argomenti \param{key} e \param{flag} per cui non ripeteremo quanto
+detto al proposito in sez.~\ref{sec:ipc_sysv_mq}. A partire dal kernel 2.6
+però sono stati introdotti degli ulteriori bit di controllo per
+l'argomento \param{flag}, specifici di \func{shmget}, attinenti alle modalità
+di gestione del segmento di memoria condivisa in relazione al sistema della
+memoria virtuale.
+
+Il primo dei due flag è \const{SHM\_HUGETLB} che consente di richiedere la
+creazione del segmento usando una \itindex{huge~page} \textit{huge page}, le
+pagine di memoria di grandi dimensioni introdotte con il kernel 2.6 per
+ottimizzare le prestazioni nei sistemi più recenti che hanno grandi quantità
+di memoria. L'operazione è privilegiata e richiede che il processo abbia la
+\itindex{capability} \textit{capability} \const{CAP\_IPC\_LOCK}. Questa
+funzionalità è specifica di Linux e non è portabile.
+
+Il secondo flag aggiuntivo, introdotto a partire dal kernel 2.6.15, è
+\const{SHM\_NORESERVE}, ed ha lo stesso scopo del flag \const{MAP\_NORESERVE}
+di \func{mmap} (vedi sez.~\ref{sec:file_memory_map}): non vengono riservate
+delle pagine di swap ad uso del meccanismo del \textit{copy on write}
+\itindex{copy~on~write} per mantenere le modifiche fatte sul segmento. Questo
+significa che caso di scrittura sul segmento quando non c'è più memoria
+disponibile, si avrà l'emissione di un \signal{SIGSEGV}.
+
+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
+deve essere specificato quando si crea un nuovo segmento di memoria con
+\const{IPC\_CREAT} o \const{IPC\_PRIVATE}, se invece si accede ad un segmento
+di memoria condivisa esistente non può essere maggiore del valore con cui esso
+è stato creato.
+
+La memoria condivisa è la forma più veloce di comunicazione fra due processi,
+in quanto permette agli stessi di vedere nel loro spazio di indirizzi una
+stessa sezione di memoria. Pertanto non è necessaria nessuna operazione di
+copia per trasmettere i dati da un processo all'altro, in quanto ciascuno può
+accedervi direttamente con le normali operazioni di lettura e scrittura dei
+dati in memoria.
+
+Ovviamente tutto questo ha un prezzo, ed il problema fondamentale della
+memoria condivisa è la sincronizzazione degli accessi. È evidente infatti che
+se un processo deve scambiare dei dati con un altro, si deve essere sicuri che
+quest'ultimo non acceda al segmento di memoria condivisa prima che il primo
+non abbia completato le operazioni di scrittura, inoltre nel corso di una
+lettura si deve essere sicuri che i dati restano coerenti e non vengono
+sovrascritti da un accesso in scrittura sullo stesso segmento da parte di un
+altro processo. Per questo in genere la memoria condivisa viene sempre
+utilizzata in abbinamento ad un meccanismo di sincronizzazione, il che, di
+norma, significa insieme a dei semafori.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{0.80\textwidth}
+ \includestruct{listati/shmid_ds.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{shmid\_ds}, associata a ciascun segmento di
+ memoria condivisa.}
+ \label{fig:ipc_shmid_ds}
+\end{figure}
+
+A ciascun segmento di memoria condivisa è associata una struttura
+\struct{shmid\_ds}, riportata in fig.~\ref{fig:ipc_shmid_ds}. Come nel caso
+delle code di messaggi quando si crea un nuovo segmento di memoria condivisa
+con \func{shmget} questa struttura viene inizializzata, in particolare il
+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*}
+\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
+ segmento, viene inizializzato al tempo corrente.
+\item i campi \var{shm\_atime} e \var{shm\_dtime}, che esprimono
+ rispettivamente il tempo dell'ultima volta che il segmento è stato
+ agganciato o sganciato da un processo, vengono inizializzati a zero.
+\item il campo \var{shm\_lpid}, che esprime il \ids{PID} del processo che ha
+ eseguito l'ultima operazione, viene inizializzato a zero.
+\item il campo \var{shm\_cpid}, che esprime il \ids{PID} del processo che ha
+ 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*}
+
+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
+di questi limiti sono al solito accessibili e modificabili attraverso
+\func{sysctl} o scrivendo direttamente nei rispettivi file di
+\file{/proc/sys/kernel/}.
+
+In tab.~\ref{tab:ipc_shm_limits} si sono riportate le
+costanti simboliche associate a ciascuno di essi, il loro significato, i
+valori preimpostati, e, quando presente, il file in \file{/proc/sys/kernel/}
+che permettono di cambiarne il valore.
+
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|c|r|c|p{7cm}|}
+ \hline
+ \textbf{Costante} & \textbf{Valore} & \textbf{File in \texttt{proc}}
+ & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{SHMALL}& 0x200000&\sysctlrelfile{kernel}{shmall}
+ & Numero massimo di pagine che
+ possono essere usate per i segmenti di
+ memoria condivisa.\\
+ \const{SHMMAX}&0x2000000&\sysctlrelfile{kernel}{shmmax}
+ & Dimensione massima di un segmento di memoria
+ condivisa.\\
+ \const{SHMMNI}& 4096&\sysctlrelfile{kernel}{msgmni}
+ & Numero massimo di segmenti di memoria condivisa
+ presenti nel kernel.\\
+ \const{SHMMIN}& 1& --- & Dimensione minima di un segmento di
+ memoria condivisa.\\
+ \const{SHMLBA}&\const{PAGE\_SIZE}&--- & Limite inferiore per le dimensioni
+ minime di un segmento (deve essere
+ allineato alle dimensioni di una
+ pagina di memoria).\\
+ \const{SHMSEG}& --- & --- & Numero massimo di segmenti di
+ memoria condivisa per ciascun
+ processo (l'implementazione non
+ prevede l'esistenza di questo
+ limite).\\
+
+
+ \hline
+ \end{tabular}
+ \caption{Valori delle costanti associate ai limiti dei segmenti di memoria
+ condivisa, insieme al relativo file in \file{/proc/sys/kernel/} ed al
+ valore preimpostato presente nel sistema.}
+ \label{tab:ipc_shm_limits}
+\end{table}
+
+Al solito la funzione di sistema che permette di effettuare le operazioni di
+controllo su un segmento di memoria condivisa è \funcd{shmctl}; il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/ipc.h}
+\fhead{sys/shm.h}
+\fdecl{int shmctl(int shmid, int cmd, struct shmid\_ds *buf)}
+
+\fdesc{Esegue le operazioni di controllo su un segmento di memoria condivisa.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EACCES}] si è richiesto \const{IPC\_STAT} ma i permessi non
+ consentono l'accesso in lettura al segmento.
+ \item[\errcode{EFAULT}] l'indirizzo specificato con \param{buf} non è
+ valido.
+ \item[\errcode{EIDRM}] l'argomento \param{shmid} fa riferimento ad un
+ segmento che è stato cancellato.
+ \item[\errcode{EINVAL}] o \param{shmid} non è un identificatore valido o
+ \param{cmd} non è un comando valido.
+ \item[\errcode{ENOMEM}] si è richiesto un \textit{memory lock} di
+ dimensioni superiori al massimo consentito.
+ \item[\errcode{EOVERFLOW}] si è tentato il comando \const{IPC\_STAT} ma il
+ valore del \ids{GID} o dell'\ids{UID} è troppo grande per essere
+ memorizzato nella struttura puntata da \param{buf}.
+ \item[\errcode{EPERM}] si è specificato un comando con \const{IPC\_SET} o
+ \const{IPC\_RMID} senza i permessi necessari.
+ \end{errlist}
+}
+\end{funcproto}
+
+Il comando specificato attraverso l'argomento \param{cmd} determina i diversi
+effetti della funzione. Nello standard POSIX.1-2001 i valori che esso può
+assumere, ed il corrispondente comportamento della funzione, sono i seguenti:
+
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{IPC\_STAT}] Legge le informazioni riguardo il segmento di memoria
+ condivisa nella struttura \struct{shmid\_ds} puntata da \param{buf}. Occorre
+ che il processo chiamante abbia il permesso di lettura sulla segmento.
+\item[\const{IPC\_RMID}] Marca il segmento di memoria condivisa per la
+ rimozione, questo verrà cancellato effettivamente solo quando l'ultimo
+ processo ad esso agganciato si sarà staccato. Questo comando può essere
+ eseguito solo da un processo con \ids{UID} effettivo corrispondente o al
+ creatore del segmento, o al proprietario del segmento, o all'amministratore.
+\item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario
+ del segmento. Per modificare i valori di \var{shm\_perm.mode},
+ \var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o
+ il creatore del segmento, oppure l'amministratore. Compiuta l'operazione
+ aggiorna anche il valore del campo \var{shm\_ctime}.
+\end{basedescript}
+
+Oltre ai precedenti su Linux sono definiti anche degli ulteriori comandi, che
+consentono di estendere le funzionalità, ovviamente non devono essere usati se
+si ha a cuore la portabilità. Questi comandi aggiuntivi sono:
+
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{SHM\_LOCK}] Abilita il \itindex{memory~locking} \textit{memory
+ locking} sul segmento di memoria condivisa, impedendo che la memoria usata
+ per il segmento venga salvata su disco dal meccanismo della
+ \index{memoria~virtuale} memoria virtuale. Come illustrato in
+ 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 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}
+ \textit{memory locking} sul segmento di memoria condivisa. Fino al kernel
+ 2.6.9 solo l'amministratore poteva utilizzare questo comando in
+ corrispondenza di un segmento da lui bloccato.
+\end{basedescript}
+
+A questi due, come per \func{msgctl} e \func{semctl}, si aggiungono tre
+ulteriori valori, \const{IPC\_INFO}, \const{MSG\_STAT} e \const{MSG\_INFO},
+introdotti ad uso del programma \cmd{ipcs} per ottenere le informazioni
+generali relative alle risorse usate dai segmenti di memoria condivisa. Dato
+che potranno essere modificati o rimossi in favore dell'uso di \texttt{/proc},
+non devono essere usati e non li tratteremo.
+
+L'argomento \param{buf} viene utilizzato solo con i comandi \const{IPC\_STAT}
+e \const{IPC\_SET} nel qual caso esso dovrà puntare ad una struttura
+\struct{shmid\_ds} precedentemente allocata, in cui nel primo caso saranno
+scritti i dati del segmento di memoria restituiti dalla funzione e da cui, nel
+secondo caso, verranno letti i dati da impostare sul segmento.
+
+Una volta che lo si è creato, per utilizzare un segmento di memoria condivisa
+l'interfaccia prevede due funzioni, \funcd{shmat} e \func{shmdt}. La prima di
+queste serve ad agganciare un segmento al processo chiamante, in modo che
+quest'ultimo possa inserirlo nel suo spazio di indirizzi per potervi accedere;
+il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/shm.h}
+\fdecl{void *shmat(int shmid, const void *shmaddr, int shmflg)}
+
+\fdesc{Aggancia un segmento di memoria condivisa al processo chiamante.}
+}
+
+{La funzione ritorna l'indirizzo del segmento in caso di successo e $-1$ (in
+ un cast a \type{void *}) per un errore, nel qual caso \var{errno} assumerà
+ uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EACCES}] il processo non ha i privilegi per accedere al
+ segmento nella modalità richiesta.
+ \item[\errcode{EINVAL}] si è specificato un identificatore invalido per
+ \param{shmid}, o un indirizzo non allineato sul confine di una pagina
+ per \param{shmaddr} o il valore \val{NULL} indicando \const{SHM\_REMAP}.
+ \end{errlist}
+ ed inoltre \errval{ENOMEM} nel suo significato generico.
+}
+\end{funcproto}
+
+La funzione inserisce un segmento di memoria condivisa all'interno dello
+spazio di indirizzi del processo, in modo che questo possa accedervi
+direttamente, la situazione dopo l'esecuzione di \func{shmat} è illustrata in
+fig.~\ref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
+ricordi quanto illustrato al proposito in sez.~\ref{sec:proc_mem_layout}). In
+particolare l'indirizzo finale del segmento dati (quello impostato da
+\func{brk}, vedi sez.~\ref{sec:proc_mem_alloc}) non viene influenzato.
+Si tenga presente infine che la funzione ha successo anche se il segmento è
+stato marcato per la cancellazione.
+
+\begin{figure}[!htb]
+ \centering \includegraphics[height=10cm]{img/sh_memory_layout}
+ \caption{Disposizione dei segmenti di memoria di un processo quando si è
+ agganciato un segmento di memoria condivisa.}
+ \label{fig:ipc_shmem_layout}
+\end{figure}
+
+L'argomento \param{shmaddr} specifica a quale indirizzo\footnote{lo standard
+ SVID prevede che l'argomento \param{shmaddr} sia di tipo \ctyp{char *}, così
+ come il valore di ritorno della funzione; in Linux è stato così con le
+ \acr{libc4} e le \acr{libc5}, con il passaggio alla \acr{glibc} il tipo di
+ \param{shmaddr} è divenuto un \ctyp{const void *} e quello del valore di
+ ritorno un \ctyp{void *} seguendo POSIX.1-2001.} deve essere associato il
+segmento, se il valore specificato è \val{NULL} è il sistema a scegliere
+opportunamente un'area di memoria libera (questo è il modo più portabile e
+sicuro di usare la funzione). Altrimenti il kernel aggancia il segmento
+all'indirizzo specificato da \param{shmaddr}; questo però può avvenire solo se
+l'indirizzo coincide con il limite di una pagina, cioè se è un multiplo esatto
+del parametro di sistema \const{SHMLBA}, che in Linux è sempre uguale
+\const{PAGE\_SIZE}.
+
+Si tenga presente però che quando si usa \val{NULL} come valore di
+\param{shmaddr}, l'indirizzo restituito da \func{shmat} può cambiare da
+processo a processo; pertanto se nell'area di memoria condivisa si salvano
+anche degli indirizzi, si deve avere cura di usare valori relativi (in genere
+riferiti all'indirizzo di partenza del segmento).
+
+L'argomento \param{shmflg} permette di cambiare il comportamento della
+funzione; esso va specificato come maschera binaria, i bit utilizzati al
+momento sono sono tre e sono identificati dalle costanti \const{SHM\_RND},
+\const{SHM\_RDONLY} e \const{SHM\_REMAP} che vanno combinate con un OR
+aritmetico.
+
+Specificando \const{SHM\_RND} si evita che \func{shmat} ritorni un errore
+quando \param{shmaddr} non è allineato ai confini di una pagina. Si può quindi
+usare un valore qualunque per \param{shmaddr}, e il segmento verrà comunque
+agganciato, ma al più vicino multiplo di \const{SHMLBA}; il nome della
+costante sta infatti per \textit{rounded}, e serve per specificare un
+indirizzo come arrotondamento.
+
+L'uso di \const{SHM\_RDONLY} permette di agganciare il segmento in sola
+lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal
+caso un tentativo di scrivere sul segmento comporterà una
+\itindex{segment~violation} violazione di accesso con l'emissione di un
+segnale di \signal{SIGSEGV}. Il comportamento usuale di \func{shmat} è quello
+di agganciare il segmento con l'accesso in lettura e scrittura (ed il processo
+deve aver questi permessi in \var{shm\_perm}), non è prevista la possibilità
+di agganciare un segmento in sola scrittura.
+
+Infine \const{SHM\_REMAP} è una estensione specifica di Linux (quindi non
+portabile) che indica che la mappatura del segmento deve rimpiazzare ogni
+precedente mappatura esistente nell'intervallo iniziante
+all'indirizzo \param{shmaddr} e di dimensione pari alla lunghezza del
+segmento. In condizioni normali questo tipo di richiesta fallirebbe con un
+errore di \errval{EINVAL}. Ovviamente usando \const{SHM\_REMAP}
+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*}
+\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*}
+
+Come accennato in sez.~\ref{sec:proc_fork} un segmento di memoria condivisa
+agganciato ad un processo viene ereditato da un figlio attraverso una
+\func{fork}, dato che quest'ultimo riceve una copia dello spazio degli
+indirizzi del padre. Invece, dato che attraverso una \func{exec} viene
+eseguito un diverso programma con uno spazio di indirizzi completamente
+diverso, tutti i segmenti agganciati al processo originario vengono
+automaticamente sganciati. Lo stesso avviene all'uscita del processo
+attraverso una \func{exit}.
+
+Una volta che un segmento di memoria condivisa non serve più, si può
+sganciarlo esplicitamente dal processo usando l'altra funzione
+dell'interfaccia, \funcd{shmdt}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/shm.h}
+\fdecl{int shmdt(const void *shmaddr)}
+
+\fdesc{Sgancia dal processo un segmento di memoria condivisa.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, la funzione
+ fallisce solo quando non c'è un segmento agganciato
+ all'indirizzo \param{shmaddr}, con \var{errno} che assume il valore
+ \errval{EINVAL}.
+}
+\end{funcproto}
+
+La funzione sgancia dallo spazio degli indirizzi del processo un segmento di
+memoria condivisa; questo viene identificato con l'indirizzo \param{shmaddr}
+restituito dalla precedente chiamata a \func{shmat} con il quale era stato
+agganciato al processo.
+
+In caso di successo la funzione aggiorna anche i seguenti campi di
+\struct{shmid\_ds}:
+\begin{itemize*}
+\item il tempo \var{shm\_dtime} dell'ultima operazione di sganciamento 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
+ decrementato di uno.
+\end{itemize*}
+inoltre la regione di indirizzi usata per il segmento di memoria condivisa
+viene tolta dallo spazio di indirizzi del processo.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/SharedMem.c}
+ \end{minipage}
+ \normalsize
+ \caption{Il codice delle funzioni che permettono di creare, trovare e
+ rimuovere un segmento di memoria condivisa.}
+ \label{fig:ipc_sysv_shm_func}
+\end{figure}
+
+Come esempio di uso di queste funzioni vediamo come implementare una serie di
+funzioni di libreria che ne semplifichino l'uso, automatizzando le operazioni
+più comuni; il codice, contenuto nel file \file{SharedMem.c}, è riportato in
+fig.~\ref{fig:ipc_sysv_shm_func}.
+
+La prima funzione (\texttt{\small 3--16}) è \func{ShmCreate} che, data una
+chiave, crea il segmento di memoria condivisa restituendo il puntatore allo
+stesso. La funzione comincia (\texttt{\small 6}) con il chiamare
+\func{shmget}, usando il flag \const{IPC\_CREATE} per creare il segmento
+qualora non esista, ed assegnandogli i privilegi specificati dall'argomento
+\var{perm} e la dimensione specificata dall'argomento \var{shm\_size}. In
+caso di errore (\texttt{\small 7--9}) si ritorna immediatamente un puntatore
+nullo, altrimenti (\texttt{\small 10}) si prosegue agganciando il segmento di
+memoria condivisa al processo con \func{shmat}. In caso di errore
+(\texttt{\small 11--13}) si restituisce di nuovo un puntatore nullo, infine
+(\texttt{\small 14}) si inizializza con \func{memset} il contenuto del
+segmento al valore costante specificato dall'argomento \var{fill}, e poi si
+ritorna il puntatore al segmento stesso.
+
+La seconda funzione (\texttt{\small 17--31}) è \func{ShmFind}, che, data una
+chiave, restituisce l'indirizzo del segmento ad essa associato. Anzitutto
+(\texttt{\small 22}) si richiede l'identificatore del segmento con
+\func{shmget}, ritornando (\texttt{\small 23--25}) un puntatore nullo in caso
+di errore. Poi si prosegue (\texttt{\small 26}) agganciando il segmento al
+processo con \func{shmat}, restituendo (\texttt{\small 27--29}) di nuovo un
+puntatore nullo in caso di errore, se invece non ci sono errori si restituisce
+il puntatore ottenuto da \func{shmat}.
+
+La terza funzione (\texttt{\small 32--51}) è \func{ShmRemove} che, data la
+chiave ed il puntatore associati al segmento di memoria condivisa, prima lo
+sgancia dal processo e poi lo rimuove. Il primo passo (\texttt{\small 37}) è
+la chiamata a \func{shmdt} per sganciare il segmento, restituendo
+(\texttt{\small 38--39}) un valore -1 in caso di errore. Il passo successivo
+(\texttt{\small 41}) è utilizzare \func{shmget} per ottenere l'identificatore
+associato al segmento data la chiave \var{key}. Al solito si restituisce un
+valore di -1 (\texttt{\small 42--45}) in caso di errore, mentre se tutto va
+bene si conclude restituendo un valore nullo.
+
+Benché la memoria condivisa costituisca il meccanismo di intercomunicazione
+fra processi più veloce, essa non è sempre il più appropriato, dato che, come
+abbiamo visto, si avrà comunque la necessità di una sincronizzazione degli
+accessi. Per questo motivo, quando la comunicazione fra processi è
+sequenziale, altri meccanismi come le \textit{pipe}, le \textit{fifo} o i
+socket, che non necessitano di sincronizzazione esplicita, sono da
+preferire. Essa diventa l'unico meccanismo possibile quando la comunicazione
+non è sequenziale\footnote{come accennato in sez.~\ref{sec:ipc_sysv_mq} per la
+ comunicazione non sequenziale si possono usare le code di messaggi,
+ attraverso l'uso del campo \var{mtype}, ma solo se quest'ultima può essere
+ effettuata in forma di messaggio.} o quando non può avvenire secondo una
+modalità predefinita.
+
+Un esempio classico di uso della memoria condivisa è quello del
+``\textit{monitor}'', in cui viene per scambiare informazioni fra un processo
+server, che vi scrive dei dati di interesse generale che ha ottenuto, e i
+processi client interessati agli stessi dati che così possono leggerli in
+maniera completamente asincrona. Con questo schema di funzionamento da una
+parte si evita che ciascun processo client debba compiere l'operazione,
+potenzialmente onerosa, di ricavare e trattare i dati, e dall'altra si evita
+al processo server di dover gestire l'invio a tutti i client di tutti i dati
+(non potendo il server sapere quali di essi servono effettivamente al singolo
+client).
+
+Nel nostro caso implementeremo un ``\textsl{monitor}'' di una directory: un
+processo si incaricherà di tenere sotto controllo alcuni parametri relativi ad
+una directory (il numero dei file contenuti, la dimensione totale, quante
+directory, link simbolici, file normali, ecc.) che saranno salvati in un
+segmento di memoria condivisa cui altri processi potranno accedere per
+ricavare la parte di informazione che interessa.
+
+In fig.~\ref{fig:ipc_dirmonitor_main} si è riportata la sezione principale del
+corpo del programma server, insieme alle definizioni delle altre funzioni
+usate nel programma e delle \index{variabili!globali} variabili globali,
+omettendo tutto quello che riguarda la gestione delle opzioni e la stampa
+delle istruzioni di uso a video; al solito il codice completo si trova con i
+sorgenti allegati nel file \file{DirMonitor.c}.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/DirMonitor.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice della funzione principale del programma \file{DirMonitor.c}.}
+ \label{fig:ipc_dirmonitor_main}
+\end{figure}
+
+Il programma usa delle \index{variabili!globali} variabili globali
+(\texttt{\small 2--14}) per mantenere i valori relativi agli oggetti usati per
+la comunicazione inter-processo; si è definita inoltre una apposita struttura
+\struct{DirProp} che contiene i dati relativi alle proprietà che si vogliono
+mantenere nella memoria condivisa, per l'accesso da parte dei client.
+
+Il programma, dopo la sezione, omessa, relativa alla gestione delle opzioni da
+riga di comando (che si limitano alla eventuale stampa di un messaggio di
+aiuto a video ed all'impostazione della durata dell'intervallo con cui viene
+ripetuto il calcolo delle proprietà della directory) controlla (\texttt{\small
+ 20--23}) che sia stato specificato l'argomento necessario contenente il nome
+della directory da tenere sotto controllo, senza il quale esce immediatamente
+con un messaggio di errore.
+
+Poi, per verificare che l'argomento specifichi effettivamente una directory,
+si esegue (\texttt{\small 24--26}) su di esso una \func{chdir}, uscendo
+immediatamente in caso di errore. Questa funzione serve anche per impostare
+la \index{directory~di~lavoro} directory di lavoro del programma nella
+directory da tenere sotto controllo, in vista del successivo uso della
+funzione \func{daemon}. Si noti come si è potuta fare questa scelta,
+nonostante le indicazioni illustrate in sez.~\ref{sec:sess_daemon}, per il
+particolare scopo del programma, che necessita comunque di restare all'interno
+di una directory.
+
+Infine (\texttt{\small 27--29}) si installano i gestori per i vari segnali di
+terminazione che, avendo a che fare con un programma che deve essere eseguito
+come server, sono il solo strumento disponibile per concluderne l'esecuzione.
+
+Il passo successivo (\texttt{\small 30--39}) è quello di creare gli oggetti di
+intercomunicazione necessari. Si inizia costruendo (\texttt{\small 30}) la
+chiave da usare come riferimento con il nome del programma,\footnote{si è
+ usato un riferimento relativo alla home dell'utente, supposto che i sorgenti
+ di GaPiL siano stati installati direttamente in essa. Qualora si effettui
+ una installazione diversa si dovrà correggere il programma.} dopo di che si
+richiede (\texttt{\small 31}) la creazione di un segmento di memoria condivisa
+con usando la funzione \func{ShmCreate} illustrata in precedenza (una pagina
+di memoria è sufficiente per i dati che useremo), uscendo (\texttt{\small
+ 32--35}) qualora la creazione ed il successivo agganciamento al processo non
+abbia successo. Con l'indirizzo \var{shmptr} così ottenuto potremo poi
+accedere alla memoria condivisa, che, per come abbiamo lo abbiamo definito,
+sarà vista nella forma data da \struct{DirProp}. Infine (\texttt{\small
+ 36--39}) utilizzando sempre la stessa chiave, si crea, tramite le funzioni
+di interfaccia già descritte in sez.~\ref{sec:ipc_sysv_sem}, anche un mutex,
+che utilizzeremo per regolare l'accesso alla memoria condivisa.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/ComputeValues.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice delle funzioni ausiliarie usate da \file{DirMonitor.c}.}
+ \label{fig:ipc_dirmonitor_sub}
+\end{figure}
+
+Completata l'inizializzazione e la creazione degli oggetti di
+intercomunicazione il programma entra nel ciclo principale (\texttt{\small
+ 40--49}) dove vengono eseguite indefinitamente le attività di monitoraggio.
+Il primo passo (\texttt{\small 41}) è eseguire \func{daemon} per proseguire
+con l'esecuzione in background come si conviene ad un programma demone; si
+noti che si è mantenuta, usando un valore non nullo del primo argomento, la
+\index{directory~di~lavoro} directory di lavoro corrente. Una volta che il
+programma è andato in background l'esecuzione prosegue all'interno di un ciclo
+infinito (\texttt{\small 42--48}).
+
+Si inizia (\texttt{\small 43}) bloccando il mutex con \func{MutexLock} per
+poter accedere alla memoria condivisa (la funzione si bloccherà
+automaticamente se qualche client sta leggendo), poi (\texttt{\small 44}) si
+cancellano i valori precedentemente immagazzinati nella memoria condivisa con
+\func{memset}, e si esegue (\texttt{\small 45}) un nuovo calcolo degli stessi
+utilizzando la funzione \myfunc{dir\_scan}; infine (\texttt{\small 46}) si
+sblocca il mutex con \func{MutexUnlock}, e si attende (\texttt{\small 47}) per
+il periodo di tempo specificato a riga di comando con l'opzione \code{-p}
+usando una \func{sleep}.
+
+Si noti come per il calcolo dei valori da mantenere nella memoria condivisa si
+sia usata ancora una volta la funzione \myfunc{dir\_scan}, già utilizzata (e
+descritta in dettaglio) in sez.~\ref{sec:file_dir_read}, che ci permette di
+effettuare la scansione delle voci della directory, chiamando per ciascuna di
+esse la funzione \func{ComputeValues}, che esegue tutti i calcoli necessari.
+
+Il codice di quest'ultima è riportato in fig.~\ref{fig:ipc_dirmonitor_sub}.
+Come si vede la funzione (\texttt{\small 2--16}) è molto semplice e si limita
+a chiamare (\texttt{\small 5}) la funzione \func{stat} sul file indicato da
+ciascuna voce, per ottenerne i dati, che poi utilizza per incrementare i vari
+contatori nella memoria condivisa, cui accede grazie alla
+\index{variabili!globali} variabile globale \var{shmptr}.
+
+Dato che la funzione è chiamata da \myfunc{dir\_scan}, si è all'interno del
+ciclo principale del programma, con un mutex acquisito, perciò non è
+necessario effettuare nessun controllo e si può accedere direttamente alla
+memoria condivisa usando \var{shmptr} per riempire i campi della struttura
+\struct{DirProp}; così prima (\texttt{\small 6--7}) si sommano le dimensioni
+dei file ed il loro numero, poi, utilizzando le macro di
+tab.~\ref{tab:file_type_macro}, si contano (\texttt{\small 8--14}) quanti ce
+ne sono per ciascun tipo.
+
+In fig.~\ref{fig:ipc_dirmonitor_sub} è riportato anche il codice
+(\texttt{\small 17--23}) del gestore dei segnali di terminazione, usato per
+chiudere il programma. Esso, oltre a provocare l'uscita del programma, si
+incarica anche di cancellare tutti gli oggetti di intercomunicazione non più
+necessari. Per questo anzitutto (\texttt{\small 19}) acquisisce il mutex con
+\func{MutexLock}, per evitare di operare mentre un client sta ancora leggendo
+i dati, dopo di che (\texttt{\small 20}) distacca e rimuove il segmento di
+memoria condivisa usando \func{ShmRemove}. Infine (\texttt{\small 21})
+rimuove il mutex con \func{MutexRemove} ed esce (\texttt{\small 22}).
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/ReadMonitor.c}
+ \end{minipage}
+ \normalsize
+ \caption{Codice del programma client del monitor delle proprietà di una
+ directory, \file{ReadMonitor.c}.}
+ \label{fig:ipc_dirmonitor_client}
+\end{figure}
+
+Il codice del client usato per leggere le informazioni mantenute nella memoria
+condivisa è riportato in fig.~\ref{fig:ipc_dirmonitor_client}. Al solito si è
+omessa la sezione di gestione delle opzioni e la funzione che stampa a video
+le istruzioni; il codice completo è nei sorgenti allegati, nel file
+\file{ReadMonitor.c}.
+
+Una volta conclusa la gestione delle opzioni a riga di comando il programma
+rigenera (\texttt{\small 7}) con \func{ftok} la stessa chiave usata dal server
+per identificare il segmento di memoria condivisa ed il mutex, poi
+(\texttt{\small 8}) richiede con \func{ShmFind} l'indirizzo della memoria
+condivisa agganciando al contempo il segmento al processo, Infine
+(\texttt{\small 17--20}) con \func{MutexFind} si richiede l'identificatore del
+mutex. Completata l'inizializzazione ed ottenuti i riferimenti agli oggetti
+di intercomunicazione necessari viene eseguito il corpo principale del
+programma (\texttt{\small 21--33}); si comincia (\texttt{\small 22})
+acquisendo il mutex con \func{MutexLock}; qui avviene il blocco del processo
+se la memoria condivisa non è disponibile. Poi (\texttt{\small 23--31}) si
+stampano i vari valori mantenuti nella memoria condivisa attraverso l'uso di
+\var{shmptr}. Infine (\texttt{\small 41}) con \func{MutexUnlock} si rilascia
+il mutex, prima di uscire.
+
+Verifichiamo allora il funzionamento dei nostri programmi; al solito, usando
+le funzioni di libreria occorre definire opportunamente
+\code{LD\_LIBRARY\_PATH}; poi si potrà lanciare il server con:
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./dirmonitor ./}
+\end{Console}
+%$
+ed avendo usato \func{daemon} il comando ritornerà immediatamente. Una volta
+che il server è in esecuzione, possiamo passare ad invocare il client per
+verificarne i risultati, in tal caso otterremo:
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./readmon}
+Ci sono 68 file dati
+Ci sono 3 directory
+Ci sono 0 link
+Ci sono 0 fifo
+Ci sono 0 socket
+Ci sono 0 device a caratteri
+Ci sono 0 device a blocchi
+Totale 71 file, per 489831 byte
+\end{Console}
+%$
+ed un rapido calcolo (ad esempio con \code{ls -a | wc} per contare i file) ci
+permette di verificare che il totale dei file è giusto. Un controllo con
+\cmd{ipcs} ci permette inoltre di verificare la presenza di un segmento di
+memoria condivisa e di un semaforo:
+\begin{Console}
+[piccardi@gont sources]$ \textbf{ipcs}
+------ Shared Memory Segments --------
+key shmid owner perms bytes nattch status
+0xffffffff 54067205 piccardi 666 4096 1
+
+------ Semaphore Arrays --------
+key semid owner perms nsems
+0xffffffff 229376 piccardi 666 1
+
+------ Message Queues --------
+key msqid owner perms used-bytes messages
+\end{Console}
+%$
+
+Se a questo punto aggiungiamo un file, ad esempio con \code{touch prova},
+potremo verificare che, passati nel peggiore dei casi almeno 10 secondi (o
+l'eventuale altro intervallo impostato per la rilettura dei dati) avremo:
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./readmon}
+Ci sono 69 file dati
+Ci sono 3 directory
+Ci sono 0 link
+Ci sono 0 fifo
+Ci sono 0 socket
+Ci sono 0 device a caratteri
+Ci sono 0 device a blocchi
+Totale 72 file, per 489887 byte
+\end{Console}
+%$
+
+A questo punto possiamo far uscire il server inviandogli un segnale di
+\signal{SIGTERM} con il comando \code{killall dirmonitor}, a questo punto
+ripetendo la lettura, otterremo un errore:
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./readmon}
+Cannot find shared memory: No such file or directory
+\end{Console}
+%$
+e inoltre potremo anche verificare che anche gli oggetti di intercomunicazione
+visti in precedenza sono stati regolarmente cancellati:
+\begin{Console}
+[piccardi@gont sources]$ \textbf{ipcs}
+------ Shared Memory Segments --------
+key shmid owner perms bytes nattch status
+
+------ Semaphore Arrays --------
+key semid owner perms nsems
+
+------ Message Queues --------
+key msqid owner perms used-bytes messages
+\end{Console}
+%$
+
+
+%% Per capire meglio il funzionamento delle funzioni facciamo ancora una volta
+%% riferimento alle strutture con cui il kernel implementa i segmenti di memoria
+%% condivisa; uno schema semplificato della struttura è illustrato in
+%% fig.~\ref{fig:ipc_shm_struct}.
+
+%% \begin{figure}[!htb]
+%% \centering
+%% \includegraphics[width=10cm]{img/shmstruct}
+%% \caption{Schema dell'implementazione dei segmenti di memoria condivisa in
+%% Linux.}
+%% \label{fig:ipc_shm_struct}
+%% \end{figure}
+
+
+
+
+\section{Tecniche alternative}
+\label{sec:ipc_alternatives}
+
+Come abbiamo detto in sez.~\ref{sec:ipc_sysv_generic}, e ripreso nella
+descrizione dei singoli oggetti che ne fan parte, il \textit{SysV-IPC}
+presenta numerosi problemi; in \cite{APUE}\footnote{in particolare nel
+ capitolo 14.} Stevens ne effettua una accurata analisi (alcuni dei concetti
+sono già stati accennati in precedenza) ed elenca alcune possibili tecniche
+alternative, che vogliamo riprendere in questa sezione.
+
+
+\subsection{Alternative alle code di messaggi}
+\label{sec:ipc_mq_alternative}
+
+Le code di messaggi sono probabilmente il meno usato degli oggetti del
+\textit{SysV-IPC}; esse infatti nacquero principalmente come meccanismo di
+comunicazione bidirezionale quando ancora le \textit{pipe} erano
+unidirezionali; con la disponibilità di \func{socketpair} (vedi
+sez.~\ref{sec:ipc_socketpair}) o utilizzando una coppia di \textit{pipe}, si
+può ottenere questo risultato senza incorrere nelle complicazioni introdotte
+dal \textit{SysV-IPC}.
+
+In realtà, grazie alla presenza del campo \var{mtype}, le code di messaggi
+hanno delle caratteristiche ulteriori, consentendo una classificazione dei
+messaggi ed un accesso non rigidamente sequenziale; due caratteristiche che
+sono impossibili da ottenere con le \textit{pipe} e i socket di
+\func{socketpair}. A queste esigenze però si può comunque ovviare in maniera
+diversa con un uso combinato della memoria condivisa e dei meccanismi di
+sincronizzazione, per cui alla fine l'uso delle code di messaggi classiche è
+relativamente poco diffuso.
+
+% TODO: trattare qui, se non si trova posto migliore, copy_from_process e
+% copy_to_process, introdotte con il kernel 3.2. Vedi
+% http://lwn.net/Articles/405346/ e
+% http://ozlabs.org/~cyeoh/cma/process_vm_readv.txt
+
+
+\subsection{I \textsl{file di lock}}
+\label{sec:ipc_file_lock}
+
+\index{file!di lock|(}
+
+Come illustrato in sez.~\ref{sec:ipc_sysv_sem} i semafori del \textit{SysV-IPC}
+presentano una interfaccia inutilmente complessa e con alcuni difetti
+strutturali, per questo quando si ha una semplice esigenza di sincronizzazione
+per la quale basterebbe un semaforo binario (quello che abbiamo definito come
+\textit{mutex}), per indicare la disponibilità o meno di una risorsa, senza la
+necessità di un contatore come i semafori, si possono utilizzare metodi
+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
+ 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
+ particolare per Linux, nel caso di NFS, si è comunque soggetti alla
+ possibilità di una \itindex{race~condition} \textit{race condition}.} che
+essa ritorni un errore quando usata con i flag di \const{O\_CREAT} e
+\const{O\_EXCL}. In tal modo la creazione di un \textsl{file di lock} può
+essere eseguita atomicamente, il processo che crea il file con successo si può
+considerare come titolare del lock (e della risorsa ad esso associata) mentre
+il rilascio si può eseguire con una chiamata ad \func{unlink}.
+
+Un esempio dell'uso di questa funzione è mostrato dalle funzioni
+\func{LockFile} ed \func{UnlockFile} riportate in fig.~\ref{fig:ipc_file_lock}
+(sono contenute in \file{LockFile.c}, un altro dei sorgenti allegati alla
+guida) che permettono rispettivamente di creare e rimuovere un \textsl{file di
+ lock}. Come si può notare entrambe le funzioni sono elementari; la prima
+(\texttt{\small 4--10}) si limita ad aprire il file di lock (\texttt{\small
+ 9}) nella modalità descritta, mentre la seconda (\texttt{\small 11--17}) lo
+cancella con \func{unlink}.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/LockFile.c}
+ \end{minipage}
+ \normalsize
+ \caption{Il codice delle funzioni \func{LockFile} e \func{UnlockFile} che
+ permettono di creare e rimuovere un \textsl{file di lock}.}
+ \label{fig:ipc_file_lock}
+\end{figure}
+
+Uno dei limiti di questa tecnica è che, come abbiamo già accennato in
+sez.~\ref{sec:file_open_close}, questo comportamento di \func{open} può non
+funzionare (la funzione viene eseguita, ma non è garantita l'atomicità
+dell'operazione) se il filesystem su cui si va ad operare è su NFS; in tal
+caso si può adottare una tecnica alternativa che prevede l'uso della
+\func{link} per creare come \textsl{file di lock} un hard link ad un file
+esistente; se il link esiste già e la funzione fallisce, significa che la
+risorsa è bloccata e potrà essere sbloccata solo con un \func{unlink},
+altrimenti il link è creato ed il lock acquisito; il controllo e l'eventuale
+acquisizione sono atomici; la soluzione funziona anche su NFS, ma ha un altro
+difetto è che è quello di poterla usare solo se si opera all'interno di uno
+stesso filesystem.
+
+In generale comunque l'uso di un \textsl{file di lock} presenta parecchi
+problemi che non lo rendono una alternativa praticabile per la
+sincronizzazione: anzitutto in caso di terminazione imprevista del processo,
+si lascia allocata la risorsa (il \textsl{file di lock}) e questa deve essere
+sempre cancellata esplicitamente. Inoltre il controllo della disponibilità
+può essere eseguito solo con una tecnica di \itindex{polling}
+\textit{polling}, ed è quindi molto inefficiente.
+
+La tecnica dei file di lock ha comunque una sua utilità, e può essere usata
+con successo quando l'esigenza è solo quella di segnalare l'occupazione di una
+risorsa, senza necessità di attendere che questa si liberi; ad esempio la si
+usa spesso per evitare interferenze sull'uso delle porte seriali da parte di
+più programmi: qualora si trovi un file di lock il programma che cerca di
+accedere alla seriale si limita a segnalare che la risorsa non è disponibile.
+
+\index{file!di lock|)}
+
+
+\subsection{La sincronizzazione con il \textit{file locking}}
+\label{sec:ipc_lock_file}
+
+Dato che i \index{file!di lock} file di lock presentano gli inconvenienti
+illustrati in precedenza, la tecnica alternativa di sincronizzazione più
+comune è quella di fare ricorso al \itindex{file~locking} \textit{file
+ locking} (trattato in sez.~\ref{sec:file_locking}) usando \func{fcntl} su un
+file creato per l'occasione per ottenere un write lock. In questo modo potremo
+usare il lock come un \textit{mutex}: per bloccare la risorsa basterà
+acquisire il lock, per sbloccarla basterà rilasciare il lock. Una richiesta
+fatta con un write lock metterà automaticamente il processo in stato di
+attesa, senza necessità di ricorrere al \itindex{polling} \textit{polling} per
+determinare la disponibilità della risorsa, e al rilascio della stessa da
+parte del processo che la occupava si otterrà il nuovo lock atomicamente.
+
+Questo approccio presenta il notevole vantaggio che alla terminazione di un
+processo tutti i lock acquisiti vengono rilasciati automaticamente (alla
+chiusura dei relativi file) e non ci si deve preoccupare di niente; inoltre
+non consuma risorse permanentemente allocate nel sistema. Lo svantaggio è che,
+dovendo fare ricorso a delle operazioni sul filesystem, esso è in genere
+leggermente più lento.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/MutexLocking.c}
+ \end{minipage}
+ \normalsize
+ \caption{Il codice delle funzioni che permettono per la gestione dei
+ \textit{mutex} con il \itindex{file~locking} \textit{file locking}.}
+ \label{fig:ipc_flock_mutex}
+\end{figure}
+
+Il codice delle varie funzioni usate per implementare un mutex utilizzando il
+\textit{file locking} \itindex{file~locking} è riportato in
+fig.~\ref{fig:ipc_flock_mutex}; si è mantenuta volutamente una struttura
+analoga alle precedenti funzioni che usano i semafori, anche se le due
+interfacce non possono essere completamente equivalenti, specie per quanto
+riguarda la rimozione del mutex.
+
+La prima funzione (\texttt{\small 1--5}) è \func{CreateMutex}, e serve a
+creare il mutex; la funzione è estremamente semplice, e si limita
+(\texttt{\small 4}) a creare, con una opportuna chiamata ad \func{open}, il
+file che sarà usato per il successivo \textit{file locking}, assicurandosi che
+non esista già (nel qual caso segnala un errore); poi restituisce il file
+descriptor che sarà usato dalle altre funzioni per acquisire e rilasciare il
+mutex.
+
+La seconda funzione (\texttt{\small 6--10}) è \func{FindMutex}, che, come la
+precedente, è stata definita per mantenere una analogia con la corrispondente
+funzione basata sui semafori. Anch'essa si limita (\texttt{\small 9}) ad
+aprire il file da usare per il \itindex{file~locking} \textit{file locking},
+solo che in questo caso le opzioni di \func{open} sono tali che il file in
+questione deve esistere di già.
+
+La terza funzione (\texttt{\small 11--22}) è \func{LockMutex} e serve per
+acquisire il mutex. La funzione definisce (\texttt{\small 14}) e inizializza
+(\texttt{\small 16--19}) la struttura \var{lock} da usare per acquisire un
+write lock sul file, che poi (\texttt{\small 21}) viene richiesto con
+\func{fcntl}, restituendo il valore di ritorno di quest'ultima. Se il file è
+libero il lock viene acquisito e la funzione ritorna immediatamente;
+altrimenti \func{fcntl} si bloccherà (si noti che la si è chiamata con
+\const{F\_SETLKW}) fino al rilascio del lock.
+
+La quarta funzione (\texttt{\small 24--34}) è \func{UnlockMutex} e serve a
+rilasciare il mutex. La funzione è analoga alla precedente, solo che in questo
+caso si inizializza (\texttt{\small 28--31}) la struttura \var{lock} per il
+rilascio del lock, che viene effettuato (\texttt{\small 33}) con la opportuna
+chiamata a \func{fcntl}. Avendo usato il \itindex{file~locking} \textit{file
+ locking} in semantica POSIX (si riveda quanto detto
+sez.~\ref{sec:file_posix_lock}) solo il processo che ha precedentemente
+eseguito il lock può sbloccare il mutex.
+
+La quinta funzione (\texttt{\small 36--39}) è \func{RemoveMutex} e serve a
+cancellare il mutex. Anche questa funzione è stata definita per mantenere una
+analogia con le funzioni basate sui semafori, e si limita a cancellare
+(\texttt{\small 38}) il file con una chiamata ad \func{unlink}. Si noti che in
+questo caso la funzione non ha effetto sui mutex già ottenuti con precedenti
+chiamate a \func{FindMutex} o \func{CreateMutex}, che continueranno ad essere
+disponibili fintanto che i relativi file descriptor restano aperti. Pertanto
+per rilasciare un mutex occorrerà prima chiamare \func{UnlockMutex} oppure
+chiudere il file usato per il lock.
+
+La sesta funzione (\texttt{\small 41--55}) è \func{ReadMutex} e serve a
+leggere lo stato del mutex. In questo caso si prepara (\texttt{\small 46--49})
+la solita struttura \var{lock} come l'acquisizione del lock, ma si effettua
+(\texttt{\small 51}) la chiamata a \func{fcntl} usando il comando
+\const{F\_GETLK} per ottenere lo stato del lock, e si restituisce
+(\texttt{\small 52}) il valore di ritorno in caso di errore, ed il valore del
+campo \var{l\_type} (che descrive lo stato del lock) altrimenti
+(\texttt{\small 54}). Per questo motivo la funzione restituirà -1 in caso di
+errore e uno dei due valori \const{F\_UNLCK} o \const{F\_WRLCK}\footnote{non
+ si dovrebbe mai avere il terzo valore possibile, \const{F\_RDLCK}, dato che
+ la nostra interfaccia usa solo i write lock. Però è sempre possibile che
+ siano richiesti altri lock sul file al di fuori dell'interfaccia, nel qual
+ caso si potranno avere, ovviamente, interferenze indesiderate.} in caso di
+successo, ad indicare che il mutex è, rispettivamente, libero o occupato.
+
+Basandosi sulla semantica dei file lock POSIX valgono tutte le considerazioni
+relative al comportamento di questi ultimi fatte in
+sez.~\ref{sec:file_posix_lock}; questo significa ad esempio che, al contrario
+di quanto avveniva con l'interfaccia basata sui semafori, chiamate multiple a
+\func{UnlockMutex} o \func{LockMutex} non si cumulano e non danno perciò
+nessun inconveniente.
+
+
+\subsection{Il \textit{memory mapping} anonimo}
+\label{sec:ipc_mmap_anonymous}
+
+\itindbeg{memory~mapping} Abbiamo già visto che quando i processi sono
+\textsl{correlati}, se cioè hanno almeno un progenitore comune, l'uso delle
+\textit{pipe} può costituire una valida alternativa alle code di messaggi;
+nella stessa situazione si può evitare l'uso di una memoria condivisa facendo
+ricorso al cosiddetto \textit{memory mapping} anonimo.
+
+In sez.~\ref{sec:file_memory_map} abbiamo visto come sia possibile mappare il
+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.
+
+In questo modo diventa possibile creare una memoria condivisa fra processi
+diversi, purché questi abbiano almeno un progenitore comune che ha effettuato
+il \textit{memory mapping} anonimo.\footnote{nei sistemi derivati da SysV una
+ funzionalità simile a questa viene implementata mappando il file speciale
+ \file{/dev/zero}. In tal caso i valori scritti nella regione mappata non
+ vengono ignorati (come accade qualora si scriva direttamente sul file), ma
+ restano in memoria e possono essere riletti secondo le stesse modalità usate
+ nel \textit{memory mapping} anonimo.} Vedremo come utilizzare questa tecnica
+più avanti, quando realizzeremo una nuova versione del monitor visto in
+sez.~\ref{sec:ipc_sysv_shm} che possa restituisca i risultati via rete.
+\itindend{memory~mapping}
+
+% TODO: fare esempio di mmap anonima
+
+% TODO: con il kernel 3.2 è stata introdotta un nuovo meccanismo di
+% intercomunicazione veloce chiamato Cross Memory Attach, da capire se e come
+% trattarlo qui, vedi http://lwn.net/Articles/405346/
+% https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=fcf634098c00dd9cd247447368495f0b79be12d1
+
+\section{L'intercomunicazione fra processi di POSIX}
+\label{sec:ipc_posix}
+
+Per superare i numerosi problemi del \textit{SysV-IPC}, evidenziati per i suoi
+aspetti generali in coda a sez.~\ref{sec:ipc_sysv_generic} e per i singoli
+oggetti nei paragrafi successivi, lo standard POSIX.1b ha introdotto dei nuovi
+meccanismi di comunicazione, che vanno sotto il nome di POSIX IPC, definendo
+una interfaccia completamente nuova, che tratteremo in questa sezione.
+
+
+\subsection{Considerazioni generali}
+\label{sec:ipc_posix_generic}
+
+Oggi Linux supporta tutti gli oggetti definito nello standard POSIX per l'IPC,
+ma a lungo non è stato così; la memoria condivisa è presente a partire dal
+kernel 2.4.x, i semafori sono forniti dalla \acr{glibc} nella sezione che
+implementa i \itindex{thread} \textit{thread} POSIX di nuova generazione che
+richiedono il kernel 2.6, le code di messaggi sono supportate a partire dal
+kernel 2.6.6.
+
+La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso
+degli identificatori e delle chiavi visti nel \textit{SysV-IPC}, per passare ai
+\itindex{POSIX~IPC~names} \textit{POSIX IPC names}, che sono sostanzialmente
+equivalenti ai nomi dei file. Tutte le funzioni che creano un oggetto di IPC
+POSIX prendono come primo argomento una stringa che indica uno di questi nomi;
+lo standard è molto generico riguardo l'implementazione, ed i nomi stessi
+possono avere o meno una corrispondenza sul filesystem; tutto quello che è
+richiesto è che:
+\begin{itemize*}
+\item i nomi devono essere conformi alle regole che caratterizzano i
+ \textit{pathname}, in particolare non essere più lunghi di \const{PATH\_MAX}
+ byte e terminati da un carattere nullo.
+\item se il nome inizia per una \texttt{/} chiamate differenti allo stesso
+ nome fanno riferimento allo stesso oggetto, altrimenti l'interpretazione del
+ nome dipende dall'implementazione.
+\item l'interpretazione di ulteriori \texttt{/} presenti nel nome dipende
+ dall'implementazione.
+\end{itemize*}
+
+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 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
+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 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
+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 Posix}
+\label{sec:ipc_posix_mq}
+
+Le code di messaggi POSIX sono supportate da Linux a partire dalla versione
+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 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 sulla directory \file{/dev/mqueue}; questo può essere
+fatto aggiungendo ad \conffile{/etc/fstab} una riga come:
+\begin{Example}
+mqueue /dev/mqueue mqueue defaults 0 0
+\end{Example}
+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 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)}
+
+\fdesc{Apre una coda di messaggi POSIX impostandone le caratteristiche.}
+}
+
+{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}. 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} (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
+ \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} (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]{0.90\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 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 valore viene ignorato dai
+ processi con privilegi amministrativi (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 da tutte le code di messaggi
+appartenenti ai processi di uno stesso utente, identificato dal loro
+\textit{real user ID}.
+
+Quando l'accesso alla coda non è più necessario si può chiudere il relativo
+descrittore con la funzione \funcd{mq\_close}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_close(mqd\_t mqdes)}
+
+\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 di sistema \funcd{mq\_unlink}, il cui prototipo è:
+
+\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 stessi valori riportati da \func{unlink}.
+}
+\end{funcproto}
+
+Anche in questo caso il comportamento della funzione è analogo a quello di
+\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
+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{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)}
+\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.
+
+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{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.}
+\fdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t
+ msg\_len, unsigned msg\_prio, 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{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} nel loro
+ significato generico.
+}
+\end{funcproto}
+
+Entrambe le funzioni richiedono un puntatore al testo del messaggio
+nell'argomento \param{msg\_ptr} e la relativa lunghezza in \param{msg\_len}.
+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: