+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,\footnote{il filesystem \texttt{tmpfs} è diverso da
+ un normale RAM disk, anch'esso disponibile attraverso il filesystem
+ \texttt{ramfs}, proprio perché realizza una interfaccia utilizzabile anche
+ per la memoria condivisa; esso infatti non ha dimensione fissa, ed usa
+ direttamente la cache interna del kernel (che viene usata anche per la
+ shared memory in stile SysV). In più i suoi contenuti, essendo trattati
+ direttamente dalla memoria virtuale \index{memoria~virtuale} possono essere
+ salvati sullo swap automaticamente.} 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 le
+\acr{glibc}\footnote{le funzioni sono state introdotte con le glibc-2.2.}
+richiedono di compilare i programmi con l'opzione \code{-lrt}; inoltre è
+necessario che in \file{/dev/shm} sia montato un filesystem \texttt{tmpfs};
+questo di norma viene fatto aggiungendo una riga del tipo di:
+\begin{verbatim}
+tmpfs /dev/shm tmpfs defaults 0 0
+\end{verbatim}
+ad \conffile{/etc/fstab}. In realtà si può montare un filesystem \texttt{tmpfs}
+dove si vuole, per usarlo come RAM disk, con un comando del tipo:
+\begin{verbatim}
+mount -t tmpfs -o size=128M,nr_inodes=10k,mode=700 tmpfs /mytmpfs
+\end{verbatim}
+
+Il filesystem riconosce, oltre quelle mostrate, le opzioni \texttt{uid} e
+\texttt{gid} che identificano rispettivamente utente e gruppo cui assegnarne
+la titolarità, e \texttt{nr\_blocks} che permette di specificarne la
+dimensione in blocchi, cioè in multipli di \const{PAGECACHE\_SIZE} che in
+questo caso è l'unità di allocazione elementare.
+
+La funzione che permette di aprire un segmento di memoria condivisa POSIX, ed
+eventualmente di crearlo se non esiste ancora, è \funcd{shm\_open}; il suo
+prototipo è:
+\begin{prototype}{mqueue.h}
+{int shm\_open(const char *name, int oflag, mode\_t mode)}
+
+Apre un segmento di memoria condivisa.
+
+\bodydesc{La funzione restituisce un file descriptor positivo in caso di
+ successo e -1 in caso di errore; nel quel caso \var{errno} assumerà gli
+ stessi valori riportati da \func{open}.}
+\end{prototype}
+
+La funzione apre un segmento di memoria condivisa identificato dal nome
+\param{name}. Come già spiegato in sez.~\ref{sec:ipc_posix_generic} questo nome
+può essere specificato in forma standard solo facendolo iniziare per \file{/}
+e senza ulteriori \file{/}, Linux supporta comunque nomi generici, che
+verranno interpretati prendendo come radice \file{/dev/shm}.\footnote{occorre
+ pertanto evitare di specificare qualcosa del tipo \file{/dev/shm/nome}
+ all'interno di \param{name}, perché questo comporta, da parte delle funzioni
+ di libreria, il tentativo di accedere a \file{/dev/shm/dev/shm/nome}.}
+
+La funzione è del tutto analoga ad \func{open} ed analoghi sono i valori che
+possono essere specificati per \param{oflag}, che deve essere specificato come
+maschera binaria comprendente almeno uno dei due valori \const{O\_RDONLY} e
+\const{O\_RDWR}; i valori possibili per i vari bit sono quelli visti in
+tab.~\ref{tab:file_open_flags} dei quali però \func{shm\_open} riconosce solo
+i seguenti:
+\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}}
+\item[\const{O\_RDONLY}] Apre il file descriptor associato al segmento di
+ memoria condivisa per l'accesso in sola lettura.
+\item[\const{O\_RDWR}] Apre il file descriptor associato al segmento di
+ memoria condivisa per l'accesso in lettura e scrittura.
+\item[\const{O\_CREAT}] Necessario qualora si debba creare il segmento di
+ memoria condivisa se esso non esiste; in questo caso viene usato il valore
+ di \param{mode} per impostare i permessi, che devono essere compatibili con
+ le modalità con cui si è aperto il file.
+\item[\const{O\_EXCL}] Se usato insieme a \const{O\_CREAT} fa fallire la
+ chiamata a \func{shm\_open} se il segmento esiste già, altrimenti esegue la
+ creazione atomicamente.
+\item[\const{O\_TRUNC}] Se il segmento di memoria condivisa esiste già, ne
+ tronca le dimensioni a 0 byte.
+\end{basedescript}
+
+In caso di successo la funzione restituisce un file descriptor associato al
+segmento di memoria condiviso con le stesse modalità di
+\func{open}\footnote{in realtà, come accennato, \func{shm\_open} è un semplice
+ wrapper per \func{open}, usare direttamente quest'ultima avrebbe lo stesso
+ effetto.} viste in sez.~\ref{sec:file_open}; in particolare viene impostato
+il flag \const{FD\_CLOEXEC}. Chiamate effettuate da diversi processi usando
+lo stesso nome, restituiranno file descriptor associati allo stesso segmento
+(così come, nel caso di file di dati, essi sono associati allo stesso
+\index{inode} inode). In questo modo è possibile effettuare una chiamata ad
+\func{mmap} sul file descriptor restituito da \func{shm\_open} ed i processi
+vedranno lo stesso segmento di memoria condivisa.
+
+Quando il nome non esiste il segmento può essere creato specificando
+\const{O\_CREAT}; in tal caso il segmento avrà (così come i nuovi file)
+lunghezza nulla. Dato che un segmento di lunghezza nulla è di scarsa utilità,
+per impostarne la dimensione si deve usare \func{ftruncate} (vedi
+sez.~\ref{sec:file_file_size}), prima di mapparlo in memoria con \func{mmap}.
+Si tenga presente che una volta chiamata \func{mmap} si può chiudere il file
+descriptor (con \func{close}), senza che la mappatura ne risenta.
+
+
+Come per i file, quando si vuole effettivamente rimuovere segmento di memoria
+condivisa, occorre usare la funzione \funcd{shm\_unlink}, il cui prototipo è:
+\begin{prototype}{mqueue.h}
+{int shm\_unlink(const char *name)}
+
+Rimuove un segmento di memoria condivisa.
+
+\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore; nel quel caso \var{errno} assumerà gli stessi valori riportati da
+ \func{unlink}.}
+\end{prototype}
+
+La funzione è del tutto analoga ad \func{unlink}, e si limita a cancellare il
+nome del segmento da \file{/dev/shm}, senza nessun effetto né sui file
+descriptor precedentemente aperti con \func{shm\_open}, né sui segmenti già
+mappati in memoria; questi verranno cancellati automaticamente dal sistema
+solo con le rispettive chiamate a \func{close} e \func{munmap}. Una volta
+eseguita questa funzione però, qualora si richieda l'apertura di un segmento
+con lo stesso nome, la chiamata a \func{shm\_open} fallirà, a meno di non aver
+usato \const{O\_CREAT}, in quest'ultimo caso comunque si otterrà un file
+descriptor che fa riferimento ad un segmento distinto da eventuali precedenti.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15.6cm}
+ \includecodesample{listati/MemShared.c}
+ \end{minipage}
+ \normalsize
+ \caption{Il codice delle funzioni di gestione dei segmenti di memoria
+ condivisa POSIX.}
+ \label{fig:ipc_posix_shmmem}
+\end{figure}
+
+Come esempio per l'uso di queste funzioni vediamo come è possibile riscrivere
+una interfaccia semplificata analoga a quella vista in
+fig.~\ref{fig:ipc_sysv_shm_func} per la memoria condivisa in stile SysV. Il
+codice, riportato in fig.~\ref{fig:ipc_posix_shmmem}, è sempre contenuto nel
+file \file{SharedMem.c} dei sorgenti allegati.
+
+La prima funzione (\texttt{\small 1--24}) è \func{CreateShm} che, dato un nome
+nell'argomento \var{name} crea un nuovo segmento di memoria condivisa,
+accessibile in lettura e scrittura, e ne restituisce l'indirizzo. Anzitutto si
+definiscono (\texttt{\small 8}) i flag per la successiva (\texttt{\small 9})
+chiamata a \func{shm\_open}, che apre il segmento in lettura e scrittura
+(creandolo se non esiste, ed uscendo in caso contrario) assegnandogli sul
+filesystem i permessi specificati dall'argomento \var{perm}. In caso di errore
+(\texttt{\small 10--12}) si restituisce un puntatore nullo, altrimenti si
+prosegue impostando (\texttt{\small 14}) la dimensione del segmento con
+\func{ftruncate}. Di nuovo (\texttt{\small 15--16}) si esce immediatamente
+restituendo un puntatore nullo in caso di errore. Poi si passa (\texttt{\small
+ 18}) a mappare in memoria il segmento con \func{mmap} specificando dei
+diritti di accesso corrispondenti alla modalità di apertura. Di nuovo si
+restituisce (\texttt{\small 19--21}) un puntatore nullo in caso di errore,
+altrimenti si inizializza (\texttt{\small 22}) il contenuto del segmento al
+valore specificato dall'argomento \var{fill} con \func{memset}, e se ne
+restituisce (\texttt{\small 23}) l'indirizzo.
+
+La seconda funzione (\texttt{\small 25--40}) è \func{FindShm} che trova un
+segmento di memoria condiviso già esistente, restituendone l'indirizzo. In
+questo caso si apre (\texttt{\small 31}) il segmento con \func{shm\_open}
+richiedendo che il segmento sia già esistente, in caso di errore
+(\texttt{\small 31--33}) si ritorna immediatamente un puntatore nullo.
+Ottenuto il file descriptor del segmento lo si mappa (\texttt{\small 35}) in
+memoria con \func{mmap}, restituendo (\texttt{\small 36--38}) un puntatore
+nullo in caso di errore, o l'indirizzo (\texttt{\small 39}) dello stesso in
+caso di successo.
+
+La terza funzione (\texttt{\small 40--45}) è \func{RemoveShm}, e serve a
+cancellare un segmento di memoria condivisa. Dato che al contrario di quanto
+avveniva con i segmenti del 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.
+
+
+
+
+\subsection{Semafori}
+\label{sec:ipc_posix_sem}
+
+Fino alla serie 2.4.x del kernel esisteva solo una implementazione parziale
+dei semafori POSIX che li realizzava solo a livello di \itindex{thread}
+\textit{thread} e non di processi,\footnote{questo significava che i semafori
+ erano visibili solo all'interno dei \itindex{thread} \textit{thread} creati
+ da un singolo processo, e non potevano essere usati come meccanismo di
+ sincronizzazione fra processi diversi.} fornita attraverso la sezione delle
+estensioni \textit{real-time} delle \acr{glibc}.\footnote{quelle che si
+ accedono collegandosi alla libreria \texttt{librt}.} Esisteva inoltre una
+libreria che realizzava (parzialmente) l'interfaccia POSIX usando le funzioni
+dei semafori di SysV IPC (mantenendo così tutti i problemi sottolineati in
+sez.~\ref{sec:ipc_sysv_sem}).
+
+A partire dal kernel 2.5.7 è stato introdotto un meccanismo di
+sincronizzazione completamente nuovo, basato sui cosiddetti
+\textit{futex},\footnote{la sigla sta per \textit{fast user mode mutex}.} con
+il quale è stato possibile implementare una versione nativa dei semafori
+POSIX. Grazie a questo con i kernel della serie 2.6 e le nuove versioni delle
+\acr{glibc} che usano questa nuova infrastruttura per quella che viene quella
+che viene chiamata \textit{New Posix Thread Library}, sono state implementate
+anche tutte le funzioni dell'interfaccia dei semafori POSIX.
+
+Anche in questo caso è necessario appoggiarsi alla libreria per le estensioni
+\textit{real-time} \texttt{librt}, questo significa che se si vuole utilizzare
+questa interfaccia, oltre ad utilizzare gli opportuni file di definizione,
+occorrerà compilare i programmi con l'opzione \texttt{-lrt}.
+
+La funzione che permette di creare un nuovo semaforo POSIX, creando il
+relativo file, o di accedere ad uno esistente, è \funcd{sem\_open}, questa
+prevede due forme diverse a seconda che sia utilizzata per aprire un semaforo
+esistente o per crearne uno nuovi, i relativi prototipi sono:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{sem\_t *sem\_open(const char *name, int oflag)}
+
+ \funcdecl{sem\_t *sem\_open(const char *name, int oflag, mode\_t mode,
+ unsigned int value)}
+
+ Crea un semaforo o ne apre uno esistente.
+
+ \bodydesc{La funzione restituisce l'indirizzo del semaforo in caso di
+ successo e \const{SEM\_FAILED} in caso di errore; nel quel caso
+ \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EACCESS}] il semaforo esiste ma non si hanno permessi
+ sufficienti per accedervi.
+ \item[\errcode{EEXIST}] si sono specificati \const{O\_CREAT} e
+ \const{O\_EXCL} ma il semaforo esiste.
+ \item[\errcode{EINVAL}] il valore di \param{value} eccede
+ \const{SEM\_VALUE\_MAX}.
+ \item[\errcode{ENAMETOOLONG}] si è utilizzato un nome troppo lungo.
+ \item[\errcode{ENOENT}] non si è usato \const{O\_CREAT} ed il nome
+ specificato non esiste.
+ \end{errlist}
+ ed inoltre \errval{ENFILE} ed \errval{ENOMEM}.}
+\end{functions}
+
+L'argomento \param{name} definisce il nome del semaforo che si vuole
+utilizzare, ed è quello che permette a processi diversi di accedere allo
+stesso semaforo. Questo deve essere specificato con un pathname nella forma
+\texttt{/qualchenome}, che non ha una corrispondenza diretta con un pathname
+reale; con Linux infatti i file associati ai semafori sono mantenuti nel
+filesystem virtuale \texttt{/dev/shm}, e gli viene assegnato automaticamente
+un nome nella forma \texttt{sem.qualchenome}.\footnote{si ha cioè una
+ corrispondenza per cui \texttt{/qualchenome} viene rimappato, nella
+ creazione tramite \func{sem\_open}, su \texttt{/dev/shm/sem.qualchenome}.}
+
+L'argomento \param{oflag} è quello che controlla le modalità con cui opera la
+funzione, ed è passato come maschera binaria; i bit corrispondono a quelli
+utilizzati per l'analogo argomento di \func{open}, anche se dei possibili
+valori visti in sez.~\ref{sec:file_open} sono utilizzati soltanto
+\const{O\_CREAT} e \const{O\_EXCL}.
+
+Se si usa \const{O\_CREAT} si richiede la creazione del semaforo qualora
+questo non esista, ed in tal caso occorre utilizzare la seconda forma della
+funzione, in cui si devono specificare sia un valore iniziale con l'argomento
+\param{value},\footnote{e si noti come così diventa possibile, differenza di
+ quanto avviene per i semafori del \textit{SysV IPC}, effettuare in maniera
+ atomica creazione ed inizializzazione di un semaforo usando una unica
+ funzione.} che una maschera dei permessi con l'argomento
+\param{mode};\footnote{anche questo argomento prende gli stessi valori
+ utilizzati per l'analogo di \func{open}, che si sono illustrati in dettaglio
+ sez.~\ref{sec:file_perm_overview}.} questi verranno assegnati al semaforo
+appena creato. Se il semaforo esiste già i suddetti valori saranno invece
+ignorati. Usando il flag \const{O\_EXCL} si richiede invece la verifica che il
+semaforo non esiste, usandolo insieme ad \const{O\_CREAT} la funzione fallisce
+qualora un semaforo con lo stesso nome sia già presente.
+
+La funzione restituisce in caso di successo un puntatore all'indirizzo del
+semaforo con un valore di tipo \ctyp{sem\_t *}, è questo valore che dovrà
+essere passato alle altre funzioni per operare sul semaforo stesso. Si tenga
+presente che, come accennato in sez.~\ref{sec:ipc_posix_generic}, i semafori
+usano la semantica standard dei file per quanto riguarda i controlli di
+accesso.
+
+Questo significa che un nuovo semaforo viene sempre creato con l'user-ID ed il
+group-ID effettivo del processo chiamante, e che i permessi indicati con
+\param{mode} vengono filtrati dal valore della \itindex{umask} \textit{umask}
+del processo. Inoltre per poter aprire un semaforo è necessario avere su di
+esso sia il permesso di lettura che quello di scrittura.
+
+Una volta che si sia ottenuto l'indirizzo di un semaforo, sarà possibile
+utilizzarlo; se si ricorda quanto detto all'inizio di
+sez.~\ref{sec:ipc_sysv_sem}, dove si sono introdotti i concetti generali
+relativi ai semafori, le operazioni principali sono due, quella che richiede
+l'uso di una risorsa bloccando il semaforo e quella che rilascia la risorsa
+liberando il semaforo. La prima operazione è effettuata dalla funzione
+\funcd{sem\_wait}, il cui prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_wait(sem\_t *sem)}
+
+ Blocca il semaforo \param{sem}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione cerca di decrementare il valore del semaforo indicato dal
+puntatore \param{sem}, se questo ha un valore positivo, cosa che significa che
+la risorsa è disponibile, la funzione ha successo, il valore del semaforo
+viene diminuito di 1 ed essa ritorna immediatamente; se il valore è nullo la
+funzione si blocca fintanto che il valore del semaforo non torni
+positivo\footnote{ovviamente per opera di altro processo che lo rilascia
+ chiamando \func{sem\_post}.} così che poi essa possa decrementarlo con
+successo e proseguire.
+
+Si tenga presente che la funzione può sempre essere interrotta da un segnale
+(nel qual caso si avrà un errore di \const{EINTR}) e che questo avverrà
+comunque, anche se si è richiesta la semantica BSD installando il relativo
+gestore con \const{SA\_RESTART} (vedi sez.~\ref{sec:sig_sigaction}) per
+riavviare le system call interrotte.
+
+Della funzione \func{sem\_wait} esistono due varianti che consentono di
+gestire diversamente le modalità di attesa in caso di risorsa occupata, la
+prima di queste è \funcd{sem\_trywait}, che serve ad effettuare un tentativo
+di acquisizione senza bloccarsi; il suo prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_trywait(sem\_t *sem)}
+
+ Tenta di bloccare il semaforo \param{sem}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà gli stessi valori:
+ \begin{errlist}
+ \item[\errcode{EAGAIN}] il semaforo non può essere acquisito senza
+ bloccarsi.
+ \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione è identica a \func{sem\_wait} ed se la risorsa è libera ha lo
+stesso effetto, vale a dire che in caso di semaforo diverso da zero la
+funzione lo decrementa e ritorna immediatamente; la differenza è che nel caso
+in cui il semaforo è occupato essa non si blocca e di nuovo ritorna
+immediatamente, restituendo però un errore di \errval{EAGAIN}, così che il
+programma possa proseguire.
+
+La seconda variante di \func{sem\_wait} è una estensione specifica che può
+essere utilizzata soltanto se viene definita la macro \macro{\_XOPEN\_SOURCE}
+ad un valore di 600 prima di includere \texttt{semaphore.h}, la funzione è
+\func{sem\_timedwait}, ed il suo prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_timedwait(sem\_t *sem, const struct timespec
+ *abs\_timeout)}
+
+ Blocca il semaforo \param{sem}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà gli stessi valori:
+ \begin{errlist}
+ \item[\errcode{ETIMEDOUT}] è scaduto il tempo massimo di attesa.
+ \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \end{errlist}
+}
+\end{functions}
+
+Anche in questo caso il comportamento della funzione è identico a quello di
+\func{sem\_wait}, la sola differenza consiste nel fatto che con questa
+funzione è possibile impostare tramite l'argomento \param{abs\_timeout} un
+tempo limite per l'attesa, scaduto il quale la funzione ritorna comunque,
+anche se non è possibile acquisire il semaforo. In tal caso la funzione
+fallirà, riportando un errore di \errval{ETIMEDOUT}.
+
+La seconda funzione principale utilizzata per l'uso dei semafori è
+\funcd{sem\_post}, che viene usata per rilasciare un semaforo occupato o, in
+generale, per aumentare di una unità il valore dello stesso anche qualora non
+fosse occupato;\footnote{si ricordi che in generale un semaforo viene usato
+ come indicatore di un numero di risorse disponibili.} il suo prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_post(sem\_t *sem)}
+
+ Rilascia il semaforo \param{sem}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione incrementa di uno il valore corrente del semaforo indicato
+dall'argomento \param{sem}, se questo era nullo la relativa risorsa risulterà
+sbloccata, cosicché un altro processo (o \itindex{thread} \textit{thread})
+eventualmente bloccato in una \func{sem\_wait} sul semaforo potrà essere
+svegliato e rimesso in esecuzione. Si tenga presente che la funzione è sicura
+\index{funzioni!sicure} per l'uso all'interno di un gestore di segnali (si
+ricordi quanto detto in sez.~\ref{sec:sig_signal_handler}).
+
+Se invece di operare su un semaforo se ne vuole solamente leggere il valore,
+si può usare la funzione \funcd{sem\_getvalue}, il cui prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_getvalue(sem\_t *sem, int *sval)}
+
+ Richiede il valore del semaforo \param{sem}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione legge il valore del semaforo indicato dall'argomento \param{sem} e
+lo restituisce nella variabile intera puntata dall'argomento
+\param{sval}. Qualora ci siano uno o più processi bloccati in attesa sul
+semaforo lo standard prevede che la funzione possa restituire un valore nullo
+oppure il numero di processi bloccati in una \func{sem\_wait} sul suddetto
+semaforo; nel caso di Linux vale la prima opzione.
+
+Questa funzione può essere utilizzata per avere un suggerimento sullo stato di
+un semaforo, ovviamente non si può prendere il risultato riportato in
+\param{sval} che come indicazione, il valore del semaforo infatti potrebbe
+essere già stato modificato al ritorno della funzione.
+
+% TODO verificare comportamento sem_getvalue
+
+Una volta che non ci sia più la necessità di operare su un semaforo se ne può
+terminare l'uso con la funzione \funcd{sem\_close}, il cui prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_close(sem\_t *sem)}
+
+ Chiude il semaforo \param{sem}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] il semaforo \param{sem} non esiste.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione chiude il semaforo indicato dall'argomento \param{sem}; questo
+comporta che tutte le risorse che il sistema può avere assegnato al processo
+nell'uso dello stesso vengono rilasciate. Questo significa che un altro
+processo bloccato sul semaforo a causa della acquisizione da parte del
+processo che chiama \func{sem\_close} potrà essere riavviato.
+
+Si tenga presente poi che come per i file all'uscita di un processo tutti i
+semafori che questo aveva aperto vengono automaticamente chiusi; questo
+comportamento risolve il problema che si aveva con i semafori del \textit{SysV
+ IPC} (di cui si è parlato in sez.~\ref{sec:ipc_sysv_sem}) per i quali le
+risorse possono restare bloccate. Si tenga poi presente che, a differenza di
+quanto avviene per i file, in caso di una chiamata ad \func{execve} tutti i
+semafori vengono chiusi automaticamente.
+
+Come per i semafori del \textit{SysV IPC} anche quelli POSIX hanno una
+persistenza di sistema; questo significa che una volta che si è creato un
+semaforo con \func{sem\_open} questo continuerà ad esistere fintanto che il
+kernel resta attivo (vale a dire fino ad un successivo riavvio) a meno che non
+lo si cancelli esplicitamente. Per far questo si può utilizzare la funzione
+\funcd{sem\_unlink}, il cui prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_unlink(const char *name)}
+
+ Rimuove il semaforo \param{name}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EACCESS}] non si hanno i permessi necessari a cancellare il
+ semaforo.
+ \item[\errcode{ENAMETOOLONG}] il nome indicato è troppo lungo.
+ \item[\errcode{ENOENT}] il semaforo \param{name} non esiste.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione rimuove il semaforo indicato dall'argomento \param{name}, che
+prende un valore identico a quello usato per creare il semaforo stesso con
+\func{sem\_open}. Il semaforo viene rimosso dal filesystem immediatamente; ma
+il semaforo viene effettivamente cancellato dal sistema soltanto quando tutti
+i processi che lo avevano aperto lo chiudono. Si segue cioè la stessa
+semantica usata con \func{unlink} per i file, trattata in dettaglio in
+sez.~\ref{sec:file_link}.
+
+Una delle caratteristiche peculiari dei semafori POSIX è che questi possono
+anche essere utilizzati anche in forma anonima, senza necessità di fare
+ricorso ad un nome sul filesystem o ad altri indicativi. In questo caso si
+dovrà porre la variabile che contiene l'indirizzo del semaforo in un tratto di
+memoria che sia accessibile a tutti i processi in gioco. La funzione che
+consente di inizializzare un semaforo anonimo è \funcd{sem\_init}, il cui
+prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_init(sem\_t *sem, int pshared, unsigned int value)}
+
+ Inizializza il semaforo anonimo \param{sem}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] il valore di \param{value} eccede
+ \const{SEM\_VALUE\_MAX}.
+ \item[\errcode{ENOSYS}] il valore di \param{pshared} non è nullo ed il
+ sistema non supporta i semafori per i processi.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione inizializza un semaforo all'indirizzo puntato dall'argomento
+\param{sem}, e come per \func{sem\_open} consente di impostare un valore
+iniziale con \param{value}. L'argomento \param{pshared} serve ad indicare se
+il semaforo deve essere utilizzato dai \itindex{thread} \textit{thread} di uno
+stesso processo (con un valore nullo) o condiviso fra processi diversi (con un
+valore non nullo).
+
+Qualora il semaforo debba essere condiviso dai \itindex{thread}
+\textit{thread} di uno stesso processo (nel qual caso si parla di
+\textit{thread-shared semaphore}), occorrerà che \param{sem} sia l'indirizzo
+di una variabile visibile da tutti i \itindex{thread} \textit{thread}, si
+dovrà usare cioè una variabile globale o una variabile allocata dinamicamente
+nello \itindex{heap} heap.
+
+Qualora il semaforo debba essere condiviso fra più processi (nel qual caso si
+parla di \textit{process-shared semaphore}) la sola scelta possibile per
+renderlo visibile a tutti è di porlo in un tratto di memoria condivisa. Questo
+potrà essere ottenuto direttamente sia con \func{shmget} (vedi
+sez.~\ref{sec:ipc_sysv_shm}) che con \func{shm\_open} (vedi
+sez.~\ref{sec:ipc_posix_shm}), oppure, nel caso che tutti i processi in gioco
+abbiano un genitore comune, con una mappatura anonima con \func{mmap} (vedi
+sez.~\ref{sec:file_memory_map}),\footnote{si ricordi che i tratti di memoria
+ condivisa vengono mantenuti nei processi figli attraverso la funzione
+ \func{fork}.} a cui essi poi potranno accedere.
+
+Una volta inizializzato il semaforo anonimo con \func{sem\_init} lo si potrà
+utilizzare nello stesso modo dei semafori normali con \func{sem\_wait} e
+\func{sem\_post}. Si tenga presente però che inizializzare due volte lo stesso
+semaforo può dar luogo ad un comportamento indefinito.
+
+
+Una volta che non si intenda più utilizzare un semaforo anonimo questo può
+essere eliminato da sistema; per far questo di deve utilizzare una apposita
+funzione, \funcd{sem\_destroy}, il cui prototipo è:
+\begin{functions}
+ \headdecl{semaphore.h}
+
+ \funcdecl{int sem\_destroy(sem\_t *sem)}
+
+ Elimina il semaforo anonimo \param{sem}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore; nel quel caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] il valore di \param{value} eccede
+ \const{SEM\_VALUE\_MAX}.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione prende come unico argomento l'indirizzo di un semaforo che deve
+essere stato inizializzato con \func{sem\_init}; non deve quindi essere
+applicata a semafori creati con \func{sem\_open}. Inoltre si deve essere
+sicuri che il semaforo sia effettivamente inutilizzato, la distruzione di un
+semaforo su cui sono presenti processi (o \itindex{thread} \textit{thread}) in
+attesa (cioè bloccati in una \func{sem\_wait}) provoca un comportamento
+indefinito.
+
+Si tenga presente infine che utilizzare un semaforo che è stato distrutto con
+\func{sem\_destroy} di nuovo può dare esito a comportamenti indefiniti. Nel
+caso ci si trovi in una tale evenienza occorre reinizializzare il semaforo una
+seconda volta con \func{sem\_init}.
+
+
+% LocalWords: like fifo System POSIX RPC Calls Common Object Request Brocker
+% LocalWords: Architecture descriptor kernel unistd int filedes errno EMFILE
+% LocalWords: ENFILE EFAULT BUF sez fig fork Stevens siblings EOF read SIGPIPE
+% LocalWords: EPIPE shell CGI Gateway Interface HTML JPEG URL mime type gs dup
+% LocalWords: barcode PostScript race condition stream BarCodePage WriteMess
+% LocalWords: size PS switch wait popen pclose stdio const char command NULL
+% LocalWords: EINVAL cap fully buffered Ghostscript l'Encapsulated epstopsf of
+% LocalWords: PDF EPS lseek ESPIPE PPM Portable PixMap format pnmcrop PNG pnm
+% LocalWords: pnmmargin png BarCode inode filesystem l'inode mknod mkfifo RDWR
+% LocalWords: ENXIO deadlock client reinviate fortunes fortunefilename daemon
+% LocalWords: FortuneServer FortuneParse FortuneClient pid libgapil LD librt
+% LocalWords: PATH linker pathname ps tmp killall fortuned crash socket domain
+% LocalWords: socketpair BSD sys protocol sv EAFNOSUPPORT EPROTONOSUPPORT AF
+% LocalWords: EOPNOTSUPP SOCK SysV IPC Process Comunication ipc perm key exec
+% LocalWords: header ftok proj stat libc SunOS glibc XPG dell'inode number uid
+% LocalWords: cuid cgid gid tab MSG shift group umask seq MSGMNI SEMMNI SHMMNI
+% LocalWords: shmmni msgmni sem sysctl IPCMNI IPCTestId msgget EACCES EEXIST
+% LocalWords: CREAT EXCL EIDRM ENOENT ENOSPC ENOMEM novo proc MSGMAX msgmax ds
+% LocalWords: MSGMNB msgmnb linked list msqid msgid linux msg qnum lspid lrpid
+% LocalWords: rtime ctime qbytes first last cbytes msgctl semctl shmctl ioctl
+% LocalWords: cmd struct buf EPERM RMID msgsnd msgbuf msgp msgsz msgflg EAGAIN
+% LocalWords: NOWAIT EINTR mtype mtext long message sizeof LENGTH ts sleep BIG
+% LocalWords: msgrcv ssize msgtyp NOERROR EXCEPT ENOMSG multiplexing select ls
+% LocalWords: poll polling queue MQFortuneServer write init HandSIGTERM l'IPC
+% LocalWords: MQFortuneClient mqfortuned mutex risorse' inter semaphore semget
+% LocalWords: nsems SEMMNS SEMMSL semid otime semval sempid semncnt semzcnt nr
+% LocalWords: SEMVMX SEMOPM semop SEMMNU SEMUME SEMAEM semnum union semun arg
+% LocalWords: ERANGE SETALL SETVAL GETALL array GETNCNT GETPID GETVAL GETZCNT
+% LocalWords: sembuf sops unsigned nsops UNDO flg nsop num undo pending semadj
+% LocalWords: sleeper scheduler running next semundo MutexCreate semunion lock
+% LocalWords: MutexFind wrapper MutexRead MutexLock MutexUnlock unlock locking
+% LocalWords: MutexRemove shmget SHMALL SHMMAX SHMMIN shmid shm segsz atime FD
+% LocalWords: dtime lpid cpid nattac shmall shmmax SHMLBA SHMSEG EOVERFLOW brk
+% LocalWords: memory shmat shmdt void shmaddr shmflg SVID RND RDONLY rounded
+% LocalWords: SIGSEGV nattch exit SharedMem ShmCreate memset fill ShmFind home
+% LocalWords: ShmRemove DirMonitor DirProp chdir GaPiL shmptr DirScan ipcs NFS
+% LocalWords: ComputeValues ReadMonitor touch SIGTERM dirmonitor unlink fcntl
+% LocalWords: LockFile UnlockFile CreateMutex FindMutex LockMutex SETLKW GETLK
+% LocalWords: UnlockMutex RemoveMutex ReadMutex UNLCK WRLCK RDLCK mapping MAP
+% LocalWords: SHARED ANONYMOUS thread patch names strace system call userid Di
+% LocalWords: groupid Michal Wronski Krzysztof Benedyczak wrona posix mqueue
+% LocalWords: lmqueue gcc mount mqd name oflag attr maxmsg msgsize receive ptr
+% LocalWords: send WRONLY NONBLOCK close mqdes EBADF getattr setattr mqstat
+% LocalWords: omqstat curmsgs flags timedsend len prio timespec abs EMSGSIZE
+% LocalWords: ETIMEDOUT timedreceive getaddr notify sigevent notification l'I
+% LocalWords: EBUSY sigev SIGNAL signo value sigval siginfo all'userid MESGQ
+% LocalWords: Konstantin Knizhnik futex tmpfs ramfs cache shared swap CONFIG
+% LocalWords: lrt blocks PAGECACHE TRUNC CLOEXEC mmap ftruncate munmap FindShm
+% LocalWords: CreateShm RemoveShm LIBRARY Library libmqueue FAILED EACCESS
+% LocalWords: ENAMETOOLONG qualchenome RESTART trywait XOPEN SOURCE timedwait
+% LocalWords: process getvalue sval execve pshared ENOSYS heap PAGE destroy