+Per inserire messaggi su di una coda sono previste due funzioni di sistema,
+\funcd{mq\_send} e \funcd{mq\_timedsend}. In realtà su Linux la \textit{system
+ call} è soltanto \func{mq\_timedsend}, mentre \func{mq\_send} viene
+implementata come funzione di libreria che si appoggia alla
+precedente. Inoltre \func{mq\_timedsend} richiede che sia definita la macro
+\macro{\_XOPEN\_SOURCE} ad un valore pari ad almeno \texttt{600} o la macro
+\macro{\_POSIX\_C\_SOURCE} ad un valore uguale o maggiore di \texttt{200112L}.
+I rispettivi prototipi sono:
+
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_send(mqd\_t mqdes, const char *msg\_ptr, size\_t msg\_len,
+ unsigned int msg\_prio)}
+\fdesc{Esegue l'inserimento di un messaggio su una coda.}
+\fhead{mqueue.h}
+\fhead{time.h}
+\fdecl{int mq\_timedsend(mqd\_t mqdes, const char *msg\_ptr, size\_t
+ msg\_len, \\
+\phantom{int mq\_timedsend(}unsigned int 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{EBADF}] si specificato un file descriptor non valido.
+ \item[\errcode{EINVAL}] si è specificato un valore nullo per
+ \param{msg\_len}, o un valore di \param{msg\_prio} fuori dai limiti, o
+ un valore non valido per \param{abs\_timeout}.
+ \item[\errcode{EMSGSIZE}] la lunghezza del messaggio \param{msg\_len}
+ eccede il limite impostato per la coda.
+ \item[\errcode{ETIMEDOUT}] l'inserimento del messaggio non è stato
+ effettuato entro il tempo stabilito (solo \func{mq\_timedsend}).
+ \end{errlist}
+ ed inoltre \errval{EBADF} e \errval{EINTR} nel loro significato generico.
+}
+\end{funcproto}
+
+Entrambe le funzioni richiedono un puntatore ad un buffer in memoria
+contenente il testo del messaggio da inserire nella coda \param{mqdes}
+nell'argomento \param{msg\_ptr}, e la relativa lunghezza in \param{msg\_len}.
+Se quest'ultima eccede la dimensione massima specificata da \var{mq\_msgsize}
+le funzioni ritornano immediatamente con un errore di \errcode{EMSGSIZE}.
+
+L'argomento \param{msg\_prio} indica la priorità dell'argomento che essendo
+definito come \ctyp{unsigned int} è sempre un intero positivo. I messaggi di
+priorità maggiore vengono inseriti davanti a quelli di priorità inferiore, e
+quindi saranno riletti per primi. A parità del valore della priorità il
+messaggio sarà inserito in coda a tutti quelli che hanno la stessa priorità
+che quindi saranno letti con la politica di una \textit{fifo}. Il valore della
+priorità non può eccedere il limite di sistema \constd{MQ\_PRIO\_MAX}, che al
+momento è pari a 32768.
+
+Qualora la coda sia piena, entrambe le funzioni si bloccano, a meno che non
+sia stata selezionata in fase di apertura della stessa la modalità non
+bloccante o non si sia impostato il flag \const{O\_NONBLOCK} sul file
+descriptor della coda, nel qual caso entrambe ritornano con un codice di
+errore di \errcode{EAGAIN}.
+
+La sola differenza fra le due funzioni è che \func{mq\_timedsend}, passato il
+tempo massimo impostato con l'argomento \param{abs\_timeout}, ritorna con un
+errore di \errcode{ETIMEDOUT}, se invece il tempo è già scaduto al momento
+della chiamata e la coda è piena la funzione ritorna immediatamente. Il valore
+di \param{abs\_timeout} deve essere specificato come tempo assoluto tramite
+una struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timespec_struct})
+indicato in numero di secondi e nanosecondi a partire dal 1 gennaio 1970.
+
+Come per l'inserimento, anche per l'estrazione dei messaggi da una coda sono
+previste due funzioni di sistema, \funcd{mq\_receive} e
+\funcd{mq\_timedreceive}. Anche in questo caso su Linux soltanto
+\func{mq\_timedreceive} è effettivamente, una \textit{system call} e per
+usarla devono essere definite le opportune macro come per
+\func{mq\_timedsend}. I rispettivi prototipi sono:
+
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{ssize\_t mq\_receive(mqd\_t mqdes, char *msg\_ptr, size\_t
+ msg\_len, unsigned int *msg\_prio)}
+\fdesc{Effettua la ricezione di un messaggio da una coda.}
+\fhead{mqueue.h}
+\fhead{time.h}
+\fdecl{ssize\_t mq\_timedreceive(mqd\_t mqdes, char *msg\_ptr, size\_t
+ msg\_len,\\
+\phantom{ssize\_t mq\_timedreceive(}unsigned int *msg\_prio, const struct timespec
+*abs\_timeout)}
+\fdesc{Riceve un messaggio da una coda entro un limite di tempo.}
+}
+{Entrambe le funzioni ritornano il numero di byte del messaggio in caso di
+ successo e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei
+ valori:
+ \begin{errlist}
+ \item[\errcode{EAGAIN}] si è aperta la coda con \const{O\_NONBLOCK}, e la
+ coda è vuota.
+ \item[\errcode{EINVAL}] si è specificato un valore nullo per
+ \param{msg\_ptr}, o un valore non valido per \param{abs\_timeout}.
+ \item[\errcode{EMSGSIZE}] la lunghezza del messaggio sulla coda eccede il
+ valore \param{msg\_len} specificato per la ricezione.
+ \item[\errcode{ETIMEDOUT}] la ricezione del messaggio non è stata
+ effettuata entro il tempo stabilito.
+ \end{errlist}
+ ed inoltre \errval{EBADF} o \errval{EINTR} nel loro significato generico. }
+\end{funcproto}
+
+La funzione estrae dalla coda \param{mqdes} il messaggio a priorità più alta,
+o il più vecchio fra quelli della stessa priorità. Una volta ricevuto il
+messaggio viene tolto dalla coda e la sua dimensione viene restituita come
+valore di ritorno; si tenga presente che 0 è una dimensione valida e che la
+condizione di errore è indicata soltanto da un valore di
+$-1$.\footnote{Stevens in \cite{UNP2} fa notare che questo è uno dei casi in
+ cui vale ciò che lo standard \textsl{non} dice, una dimensione nulla
+ infatti, pur non essendo citata, non viene proibita.}
+
+Se la dimensione specificata da \param{msg\_len} non è sufficiente a contenere
+il messaggio, entrambe le funzioni, al contrario di quanto avveniva nelle code
+di messaggi di SysV, ritornano un errore di \errcode{EMSGSIZE} senza estrarre
+il messaggio. È pertanto opportuno eseguire sempre una chiamata a
+\func{mq\_getattr} prima di eseguire una ricezione, in modo da ottenere la
+dimensione massima dei messaggi sulla coda, per poter essere in grado di
+allocare dei buffer sufficientemente ampi per la lettura.
+
+Se si specifica un puntatore per l'argomento \param{msg\_prio} il valore della
+priorità del messaggio viene memorizzato all'indirizzo da esso indicato.
+Qualora non interessi usare la priorità dei messaggi si può specificare
+\var{NULL}, ed usare un valore nullo della priorità nelle chiamate a
+\func{mq\_send}.
+
+Si noti che con le code di messaggi POSIX non si ha la possibilità di
+selezionare quale messaggio estrarre con delle condizioni sulla priorità, a
+differenza di quanto avveniva con le code di messaggi di SysV che permettono
+invece la selezione in base al valore del campo \var{mtype}.
+
+Qualora la coda sia vuota entrambe le funzioni si bloccano, a meno che non si
+sia selezionata la modalità non bloccante; in tal caso entrambe ritornano
+immediatamente con l'errore \errcode{EAGAIN}. Anche in questo caso la sola
+differenza fra le due funzioni è che la seconda non attende indefinitamente e
+passato il tempo massimo \param{abs\_timeout} ritorna comunque con un errore
+di \errcode{ETIMEDOUT}.
+
+Uno dei problemi sottolineati da Stevens in \cite{UNP2}, comuni ad entrambe le
+tipologie di code messaggi, è che non è possibile per chi riceve identificare
+chi è che ha inviato il messaggio, in particolare non è possibile sapere da
+quale utente esso provenga. Infatti, in mancanza di un meccanismo interno al
+kernel, anche se si possono inserire delle informazioni nel messaggio, queste
+non possono essere credute, essendo completamente dipendenti da chi lo invia.
+Vedremo però come, attraverso l'uso del meccanismo di notifica, sia possibile
+superare in parte questo problema.
+
+Una caratteristica specifica delle code di messaggi POSIX è la possibilità di
+usufruire di un meccanismo di notifica asincrono; questo può essere attivato
+usando la funzione \funcd{mq\_notify}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{mqueue.h}
+\fdecl{int mq\_notify(mqd\_t mqdes, const struct sigevent *notification)}
+
+\fdesc{Attiva il meccanismo di notifica per una coda.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il descrittore non fa riferimento ad una coda di
+ messaggi.
+ \item[\errcode{EBUSY}] c'è già un processo registrato per la notifica.
+ \item[\errcode{EINVAL}] si è richiesto un meccanismo di notifica invalido
+ o specificato nella notifica con i segnali il valore di un segnale non
+ esistente.
+ \end{errlist}
+ ed inoltre \errval{ENOMEM} nel suo significato generico.
+}
+\end{funcproto}
+
+Il meccanismo di notifica permette di segnalare in maniera asincrona ad un
+processo la presenza di dati sulla coda indicata da \param{mqdes}, in modo da
+evitare la necessità di bloccarsi nell'attesa. Per far questo un processo deve
+registrarsi con la funzione \func{mq\_notify}, ed il meccanismo è disponibile
+per un solo processo alla volta per ciascuna coda.
+
+Il comportamento di \func{mq\_notify} dipende dai valori passati con
+l'argomento \param{notification}, che è un puntatore ad una apposita struttura
+\struct{sigevent}, (definita in fig.~\ref{fig:struct_sigevent}) introdotta
+dallo standard POSIX.1b per gestire la notifica di eventi; per altri dettagli
+su di essa si può rivedere quanto detto in sez.~\ref{sec:sig_timer_adv} a
+proposito dell'uso della stessa struttura per la notifica delle scadenze dei
+\textit{timer}.
+
+Attraverso questa struttura si possono impostare le modalità con cui viene
+effettuata la notifica nel campo \var{sigev\_notify}, che può assumere i
+valori di tab.~\ref{tab:sigevent_sigev_notify}; fra questi la pagina di
+manuale riporta soltanto i primi tre, ed inizialmente era possibile solo
+\const{SIGEV\_SIGNAL}. Il metodo consigliato è quello di usare
+\const{SIGEV\_SIGNAL} usando il campo \var{sigev\_signo} per indicare il quale
+segnale deve essere inviato al processo. Inoltre il campo \var{sigev\_value} è
+un puntatore ad una struttura \struct{sigval} (definita in
+fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore del segnale
+un valore numerico o un indirizzo,\footnote{per il suo uso si riveda la
+ trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei segnali
+ \textit{real-time}.} posto che questo sia installato nella forma estesa
+vista in sez.~\ref{sec:sig_sigaction}.
+
+La funzione registra il processo chiamante per la notifica se
+\param{notification} punta ad una struttura \struct{sigevent} opportunamente
+inizializzata, o cancella una precedente registrazione se è \val{NULL}. Dato
+che un solo processo alla volta può essere registrato, la funzione fallisce
+con \errcode{EBUSY} se c'è un altro processo già registrato. Questo significa
+anche che se si registra una notifica con \const{SIGEV\_NONE} il processo non
+la riceverà, ma impedirà anche che altri possano registrarsi per poterlo fare.
+Si tenga presente inoltre che alla chiusura del descrittore associato alla
+coda (e quindi anche all'uscita del processo) ogni eventuale registrazione di
+notifica presente viene cancellata.
+
+La notifica del segnale avviene all'arrivo di un messaggio in una coda vuota
+(cioè solo se sulla coda non ci sono messaggi) e se non c'è nessun processo
+bloccato in una chiamata a \func{mq\_receive}, in questo caso infatti il
+processo bloccato ha la precedenza ed il messaggio gli viene immediatamente
+inviato, mentre per il meccanismo di notifica tutto funziona come se la coda
+fosse rimasta vuota.
+
+Quando un messaggio arriva su una coda vuota al processo che si era registrato
+viene inviato il segnale specificato da \code{notification->sigev\_signo}, e
+la coda diventa disponibile per una ulteriore registrazione. Questo comporta
+che se si vuole mantenere il meccanismo di notifica occorre ripetere la
+registrazione chiamando nuovamente \func{mq\_notify} all'interno del gestore
+del segnale di notifica. A differenza della situazione simile che si aveva con
+i segnali non affidabili (l'argomento è stato affrontato in
+\ref{sec:sig_semantics}) questa caratteristica non configura una \textit{race
+ condition} perché l'invio di un segnale avviene solo se la coda è vuota;
+pertanto se si vuole evitare di correre il rischio di perdere eventuali
+ulteriori segnali inviati nel lasso di tempo che occorre per ripetere la
+richiesta di notifica basta avere cura di eseguire questa operazione prima di
+estrarre i messaggi presenti dalla coda.
+
+L'invio del segnale di notifica avvalora alcuni campi di informazione
+restituiti al gestore attraverso la struttura \struct{siginfo\_t} (definita in
+fig.~\ref{fig:sig_siginfo_t}). In particolare \var{si\_pid} viene impostato al
+valore del \ids{PID} del processo che ha emesso il segnale, \var{si\_uid}
+all'\textsl{user-ID} effettivo, \var{si\_code} a \const{SI\_MESGQ}, e
+\var{si\_errno} a 0. Questo ci dice che, se si effettua la ricezione dei
+messaggi usando esclusivamente il meccanismo di notifica, è possibile ottenere
+le informazioni sul processo che ha inserito un messaggio usando un gestore
+per il segnale in forma estesa, di nuovo si faccia riferimento a quanto detto
+al proposito in sez.~\ref{sec:sig_sigaction} e sez.~\ref{sec:sig_real_time}.
+
+
+\subsection{Memoria condivisa}
+\label{sec:ipc_posix_shm}
+
+La memoria condivisa è stato il primo degli oggetti di IPC POSIX inserito nel
+kernel ufficiale; il supporto a questo tipo di oggetti è realizzato attraverso
+il filesystem \texttt{tmpfs}, uno speciale filesystem che mantiene tutti i
+suoi contenuti in memoria, che viene attivato abilitando l'opzione
+\texttt{CONFIG\_TMPFS} in fase di compilazione del kernel.
+
+Per potere utilizzare l'interfaccia POSIX per la memoria condivisa la
+\acr{glibc} (le funzioni sono state introdotte con la versione 2.2) richiede
+di compilare i programmi con l'opzione \code{-lrt}; inoltre è necessario che
+in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs}; questo di norma
+viene fatto aggiungendo una riga del tipo di:
+\begin{FileExample}[label=/etc/fstab]
+tmpfs /dev/shm tmpfs defaults 0 0
+\end{FileExample}
+ad \conffile{/etc/fstab}. In realtà si può montare un filesystem
+\texttt{tmpfs} dove si vuole, per usarlo come RAM disk, con un comando del
+tipo:
+\begin{Example}
+mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs
+\end{Example}
+
+Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e
+\texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne
+la titolarità, e \texttt{nr\_blocks} che permette di specificarne la
+dimensione in blocchi, cioè in multipli di \constd{PAGECACHE\_SIZE} che in
+questo caso è l'unità di allocazione elementare.
+
+La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed
+eventualmente di crearlo se non esiste ancora, è \funcd{shm\_open}; il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fhead{sys/stat.h}
+\fhead{fcntl.h}
+\fdecl{int shm\_open(const char *name, int oflag, mode\_t mode)}
+
+\fdesc{Apre un segmento di memoria condivisa.}
+}
+
+{La funzione ritorna un file descriptor in caso di successo e $-1$ per un
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EACCES}] non si hanno i permessi di aprire il segmento nella
+ modalità scelta o si richiesto \const{O\_TRUNC} per un segmento su cui non
+ si ha il permesso di scrittura.
+ \item[\errcode{EINVAL}] si è utilizzato un nome non valido.
+ \end{errlist}
+ ed inoltre \errval{EEXIST}, \errval{EMFILE}, \errval{ENAMETOOLONG},
+ \errval{ENFILE} e \errval{ENOENT} nello stesso significato che hanno per
+ \func{open}.
+}
+\end{funcproto}
+
+
+La funzione apre un segmento di memoria condivisa identificato dal nome
+\param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo
+nome può essere specificato in forma standard solo facendolo iniziare per
+``\texttt{/}'' e senza ulteriori ``\texttt{/}''. Linux supporta comunque nomi
+generici, che verranno interpretati prendendo come radice
+\file{/dev/shm}.\footnote{occorre pertanto evitare di specificare qualcosa del
+ tipo \file{/dev/shm/nome} all'interno di \param{name}, perché questo
+ comporta, da parte delle funzioni di libreria, il tentativo di accedere a
+ \file{/dev/shm/dev/shm/nome}.}
+
+La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
+possono essere specificati per \param{oflag}, che deve essere specificato come
+maschera binaria comprendente almeno uno dei due valori \const{O\_RDONLY} e
+\const{O\_RDWR}; i valori possibili per i vari bit sono quelli visti in
+sez.~\ref{sec:file_open_close} dei quali però \func{shm\_open} riconosce solo
+i seguenti:
+\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{O\_RDONLY}] Apre il file descriptor associato al segmento di
+ memoria condivisa per l'accesso in sola lettura.
+\item[\const{O\_RDWR}] Apre il file descriptor associato al segmento di
+ memoria condivisa per l'accesso in lettura e scrittura.
+\item[\const{O\_CREAT}] Necessario qualora si debba creare il segmento di
+ memoria condivisa se esso non esiste; in questo caso viene usato il valore
+ di \param{mode} per impostare i permessi, che devono essere compatibili con
+ le modalità con cui si è aperto il file.
+\item[\const{O\_EXCL}] Se usato insieme a \const{O\_CREAT} fa fallire la
+ chiamata a \func{shm\_open} se il segmento esiste già, altrimenti esegue la
+ creazione atomicamente.
+\item[\const{O\_TRUNC}] Se il segmento di memoria condivisa esiste già, ne
+ tronca le dimensioni a 0 byte.
+\end{basedescript}
+
+In caso di successo la funzione restituisce un file descriptor associato al
+segmento di memoria condiviso con le stesse modalità di \func{open} viste in
+sez.~\ref{sec:file_open_close}. Inoltre sul file descriptor viene sempre
+impostato il flag \const{FD\_CLOEXEC}. Chiamate effettuate da diversi
+processi usando lo stesso nome restituiranno file descriptor associati allo
+stesso segmento, così come, nel caso di file ordinari, essi sono associati
+allo stesso inode. In questo modo è possibile effettuare una chiamata ad
+\func{mmap} sul file descriptor restituito da \func{shm\_open} ed i processi
+vedranno lo stesso segmento di memoria condivisa.
+
+Quando il nome non esiste si può creare un nuovo segmento specificando
+\const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file)
+lunghezza nulla. Il nuovo segmento verrà creato con i permessi indicati
+da \param{mode} (di cui vengono usati solo i 9 bit meno significativi, non si
+applicano pertanto i permessi speciali di sez.~\ref{sec:file_special_perm})
+filtrati dal valore dell'\textit{umask} del processo. Come gruppo ed utente
+proprietario del segmento saranno presi quelli facenti parte del gruppo
+\textit{effective} del processo chiamante.
+
+Dato che un segmento di lunghezza nulla è di scarsa utilità, una vola che lo
+si è creato per impostarne la dimensione si dovrà poi usare \func{ftruncate}
+(vedi sez.~\ref{sec:file_file_size}) prima di mapparlo in memoria con
+\func{mmap}. Si tenga presente che una volta chiamata \func{mmap} si può
+chiudere il file descriptor ad esso associato (semplicemente con
+\func{close}), senza che la mappatura ne risenta, e che questa può essere
+rimossa usando \func{munmap}.
+
+Come per i file, quando si vuole rimuovere completamente un segmento di
+memoria condivisa occorre usare la funzione \funcd{shm\_unlink}, il cui
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{int shm\_unlink(const char *name)}
+
+\fdesc{Rimuove 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}] non si è proprietari del segmento.
+ \end{errlist}
+ ed inoltre \errval{ENAMETOOLONG} e \errval{ENOENT}, nel loro significato
+ generico.
+}
+\end{funcproto}
+
+La funzione è del tutto analoga ad \func{unlink}, e si limita a cancellare il
+nome del segmento da \file{/dev/shm}, senza nessun effetto né sui file
+descriptor precedentemente aperti con \func{shm\_open}, né sui segmenti già
+mappati in memoria; questi verranno cancellati automaticamente dal sistema
+solo con le rispettive chiamate a \func{close} e \func{munmap}. Una volta
+eseguita questa funzione però, qualora si richieda l'apertura di un segmento
+con lo stesso nome, la chiamata a \func{shm\_open} fallirà, a meno di non aver
+usato \const{O\_CREAT}, in quest'ultimo caso comunque si otterrà un file
+descriptor che fa riferimento ad un segmento distinto da eventuali precedenti.
+
+Dato che i segmenti di memoria condivisa sono trattati come file del
+filesystem \texttt{tmpfs}, si possono usare su di essi, con lo stesso
+significato che assumono sui file ordinari, anche funzioni come quelle delle
+famiglie \func{fstat}, \func{fchown} e \func{fchmod}. Inoltre a partire dal
+kernel 2.6.19 per i permessi sono supportate anche le ACL illustrate in
+sez.~\ref{sec:file_ACL}.
+
+Come esempio dell'uso delle funzioni attinenti ai segmenti di memoria
+condivisa POSIX, vediamo come è possibile riscrivere una interfaccia
+semplificata analoga a quella vista in fig.~\ref{fig:ipc_sysv_shm_func} per la
+memoria condivisa in stile SysV. Il codice completo, di cui si sono riportate
+le parti essenziali in fig.~\ref{fig:ipc_posix_shmmem}, è contenuto nel file
+\file{SharedMem.c} dei sorgenti allegati.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/MemShared.c}
+ \end{minipage}
+ \normalsize
+ \caption{Il codice delle funzioni di gestione dei segmenti di memoria
+ condivisa POSIX.}
+ \label{fig:ipc_posix_shmmem}
+\end{figure}
+
+La prima funzione (\texttt{\small 1-24}) è \func{CreateShm} che, dato un nome
+nell'argomento \var{name} crea un nuovo segmento di memoria condivisa,
+accessibile in lettura e scrittura, e ne restituisce l'indirizzo. Anzitutto si
+definiscono (\texttt{\small 8}) i flag per la successiva (\texttt{\small 9})
+chiamata a \func{shm\_open}, che apre il segmento in lettura e scrittura
+(creandolo se non esiste, ed uscendo in caso contrario) assegnandogli sul
+filesystem i permessi specificati dall'argomento \var{perm}.
+
+In caso di errore (\texttt{\small 10-12}) si restituisce un puntatore nullo,
+altrimenti si prosegue impostando (\texttt{\small 14}) la dimensione del
+segmento con \func{ftruncate}. Di nuovo (\texttt{\small 15-16}) si esce
+immediatamente restituendo un puntatore nullo in caso di errore. Poi si passa
+(\texttt{\small 18}) a mappare in memoria il segmento con \func{mmap}
+specificando dei diritti di accesso corrispondenti alla modalità di apertura.
+Di nuovo si restituisce (\texttt{\small 19-21}) un puntatore nullo in caso di
+errore, altrimenti si inizializza (\texttt{\small 22}) il contenuto del
+segmento al valore specificato dall'argomento \var{fill} con \func{memset}, e
+se ne restituisce (\texttt{\small 23}) l'indirizzo.
+
+La seconda funzione (\texttt{\small 25-40}) è \func{FindShm} che trova un
+segmento di memoria condiviso esistente, restituendone l'indirizzo. In questo
+caso si apre (\texttt{\small 31}) il segmento con \func{shm\_open} richiedendo
+che il segmento sia già esistente, in caso di errore (\texttt{\small 31-33})
+si ritorna immediatamente un puntatore nullo. Ottenuto il file descriptor del
+segmento lo si mappa (\texttt{\small 35}) in memoria con \func{mmap},
+restituendo (\texttt{\small 36-38}) un puntatore nullo in caso di errore, o
+l'indirizzo (\texttt{\small 39}) dello stesso in caso di successo.
+
+La terza funzione (\texttt{\small 40-45}) è \func{RemoveShm}, e serve a
+cancellare un segmento di memoria condivisa. Dato che al contrario di quanto
+avveniva con i segmenti del \textit{SysV-IPC} gli oggetti allocati nel kernel
+vengono rilasciati automaticamente quando nessuna li usa più, tutto quello che
+c'è da fare (\texttt{\small 44}) in questo caso è chiamare \func{shm\_unlink},
+restituendo al chiamante il valore di ritorno.
+
+
+