+identico è l'uso degli argomenti \param{key} e \param{flag} per cui non
+ripeteremo quanto detto al proposito in \secref{sec:ipc_sysv_mq}. L'argomento
+\param{size} specifica invece la dimensione, in byte, del segmento, che viene
+comunque arrotondata al multiplo superiore di \const{PAGE\_SIZE}.
+
+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]{15cm}
+ \begin{lstlisting}[labelstep=0]{}
+struct shmid_ds {
+ struct ipc_perm shm_perm; /* operation perms */
+ int shm_segsz; /* size of segment (bytes) */
+ time_t shm_atime; /* last attach time */
+ time_t shm_dtime; /* last detach time */
+ time_t shm_ctime; /* last change time */
+ unsigned short shm_cpid; /* pid of creator */
+ unsigned short shm_lpid; /* pid of last operator */
+ short shm_nattch; /* no. of current attaches */
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{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
+\var{shmid\_ds}, riportata in \figref{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
+\secref{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 \acr{pid} del processo che ha
+ eseguito l'ultima operazione, viene inizializzato a zero.
+\item il campo \var{shm\_cpid}, che esprime il \acr{pid} del processo che ha
+ creato il segmento, viene inizializzato al \acr{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 \tabref{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&\file{shmall}& Numero massimo di pagine che
+ possono essere usate per i segmenti di
+ memoria condivisa. \\
+ \const{SHMMAX}&0x2000000&\file{shmmax}& Dimensione massima di un segmento
+ di memoria condivisa.\\
+ \const{SHMMNI}& 4096&\file{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.\\
+
+
+ \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 che permette di effettuare le operazioni di controllo su
+un segmento di memoria condivisa è \func{shmctl}; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/ipc.h}
+ \headdecl{sys/shm.h}
+
+ \funcdecl{int shmctl(int shmid, int cmd, struct shmid\_ds *buf)}
+
+ Esegue le operazioni di controllo su un segmento di memoria condivisa.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\errcode{EACCES}] Si è richiesto \const{IPC\_STAT} ma i permessi non
+ consentono l'accesso in lettura al segmento.
+ \item[\errcode{EINVAL}] O \param{shmid} o \param{cmd} hanno valori non
+ validi.
+ \item[\errcode{EIDRM}] L'argomento \param{shmid} fa riferimento ad un
+ segmento che è stato cancellato.
+ \item[\errcode{EPERM}] Si è specificato un comando con \const{IPC\_SET} o
+ \const{IPC\_RMID} senza i permessi necessari.
+ \item[\errcode{EOVERFLOW}] L'argomento \param{shmid} fa riferimento ad un
+ segmento che è stato cancellato.
+ \end{errlist}
+ ed inoltre \const{EFAULT}.}
+\end{functions}
+
+Il comportamento della funzione dipende dal valore del comando passato
+attraverso l'argomento \param{cmd}, i valori possibili 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 \var{shmid\_ds} puntata da \param{buf}. Occorre
+ avere il permesso di lettura sulla coda.
+\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 userid effettivo corrispondente o al
+ creatore della coda, o al proprietario della coda, 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 della coda, oppure l'amministratore. Compiuta l'operazione
+ aggiorna anche il valore del campo \var{shm\_ctime}.
+\item[\const{SHM\_LOCK}] Abilita il \textit{memory locking}\index{memory
+ locking}\footnote{impedisce cioè che la memoria usata per il segmento
+ venga salvata su disco dal meccanismo della memoria virtuale; si ricordi
+ quanto trattato in \secref{sec:proc_mem_lock}.} sul segmento di memoria
+ condivisa. Solo l'amministratore può utilizzare questo comando.
+\item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento
+ di memoria condivisa. Solo l'amministratore può utilizzare questo comando.
+\end{basedescript}
+i primi tre comandi sono gli stessi già visti anche per le code ed i semafori,
+gli ultimi due sono delle estensioni previste da Linux.
+
+Per utilizzare i segmenti di memoria condivisa l'interfaccia prevede due
+funzioni, la prima è \func{shmat}, che serve ad agganciare un segmento al
+processo chiamante, in modo che quest'ultimo possa vederlo nel suo spazio di
+indirizzi; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/shm.h}
+
+ \funcdecl{void *shmat(int shmid, const void *shmaddr, int shmflg)}
+ Aggancia al processo un segmento di memoria condivisa.
+
+ \bodydesc{La funzione restituisce l'indirizzo del segmento in caso di
+ successo, e -1 in caso di errore, nel qual caso \var{errno} assumerà i
+ 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}.
+ \end{errlist}
+ ed inoltre \const{ENOMEM}.}
+\end{functions}
+
+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
+\figref{fig:ipc_shmem_layout} (per la comprensione del resto dello schema si
+ricordi quanto illustrato al proposito in \secref{sec:proc_mem_layout}). In
+particolare l'indirizzo finale del segmento dati (quello impostato da
+\func{brk}, vedi \secref{sec:proc_mem_sbrk}) 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 alle \acr{glibc} il tipo di
+ \param{shmaddr} è divenuto un \ctyp{const void *} e quello del valore di
+ ritorno un \ctyp{void *}.} 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 sono
+solo due e sono identificati dalle costanti \const{SHM\_RND} e
+\const{SHM\_RDONLY}, 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, in Linux è equivalente a \const{PAGE\_SIZE}).
+
+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 violazione di
+accesso con l'emissione di un segnale di \const{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.
+
+In caso di successo la funzione aggiorna anche i seguenti campi di
+\var{shmid\_ds}:
+\begin{itemize*}
+\item il tempo \var{shm\_atime} dell'ultima operazione di aggancio viene
+ impostato al tempo corrente.
+\item il \acr{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 \secref{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, \func{shmdt}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/shm.h}
+
+ \funcdecl{int shmdt(const void *shmaddr)}
+ Sgancia dal processo un segmento di memoria condivisa.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
+ errore, la funzione fallisce solo quando non c'è un segmento agganciato
+ all'indirizzo \func{shmaddr}, con \var{errno} che assume il valore
+ \const{EINVAL}.}
+\end{functions}
+
+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
+\var{shmid\_ds}:
+\begin{itemize*}
+\item il tempo \var{shm\_dtime} dell'ultima operazione di sganciamento viene
+ impostato al tempo corrente.
+\item il \acr{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.
+
+
+%% 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
+%% \figref{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 \secref{sec:ipc_sysv_generic}, e ripreso nella
+descrizione dei signoli oggetti che ne fan parte, il \textit{SysV IPC}
+presenta numerosi problemi; in \cite{APUE}\footnote{in particolare nel
+ capitolo 14.} Stevens ne eeffettua 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 pipe erano unidirezionali; con la
+disponibilità di \func{socketpair} (vedi \secref{sec:ipc_socketpair}) si può
+ottenere lo stesso 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 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 è poco diffuso.
+
+
+
+\subsection{I \textsl{file di lock}}
+\label{sec:ipc_file_lock}
+
+Come illustrato in \secref{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}\index{file di lock} (per i quali esiste anche una
+opportuna directory, \file{/var/lock}, nel filesystem standard). Per questo si
+usa la caratteristica della funzione \func{open} (illustrata in
+\secref{sec:file_open}) 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 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 \figref{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}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h> /* unix standard functions */
+/*
+ * Function LockFile:
+ */
+int LockFile(const char* path_name)
+{
+ return open(path_name, O_EXCL|O_CREAT);
+}
+/*
+ * Function UnlockFile:
+ */
+int UnlockFile(const char* path_name)
+{
+ return unlink(path_name);
+}
+
+ \end{lstlisting}
+ \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
+\secref{sec:file_open}, 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
+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.
+
+Un generale comunque l'uso di un \textsl{file di lock} presenta parecchi
+problemi, che non lo rendono una alternativa praticabile per la
+sincronizzazione: anzitutto anche in questo caso, in caso di terminazione
+imprevista del processo, si lascia allocata la risorsa (il file di lock) e
+questa deve essere sempre cancellata esplicitamente. Inoltre il controllo
+della disponibilità può essere eseguito solo con una tecnica di
+\textit{polling}\index{polling}, ed è quindi molto inefficiente.
+
+La tecnica dei file di lock non di meno ha 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.
+
+\subsection{La sincronizzazione con il \textit{file locking}}
+\label{sec:ipc_lock_file}
+
+Dato che i file di lock presentano gli inconvenienti illustrati in precedenza,
+la tecnica alternativa più comune è quella di fare ricorso al \textit{file
+ locking} (trattato in \secref{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 \textit{polling}\index{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}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+/*
+ * Function LockMutex: lock a file (creating it if not existent).
+ */
+int LockMutex(const char *path_name)
+{
+ int fd, res;
+ struct flock lock; /* file lock structure */
+ /* first open the file (creating it if not existent) */
+ if ( (fd = open(path_name, O_EXCL|O_CREAT)) < 0) { /* first open file */
+ return fd;
+ }
+ /* set flock structure */
+ lock.l_type = F_WRLCK; /* set type: read or write */
+ lock.l_whence = SEEK_SET; /* start from the beginning of the file */
+ lock.l_start = 0; /* set the start of the locked region */
+ lock.l_len = 0; /* set the length of the locked region */
+ /* do locking */
+ if ( (res = fcntl(fd, F_SETLKW, &lock)) < 0 ) {
+ return res;
+ }
+ return 0;
+}
+/*
+ * Function UnLockMutex: unlock a file.
+ */
+int UnlockMutex(const char *path_name)
+{
+ int fd, res;
+ struct flock lock; /* file lock structure */
+ /* first open the file */
+ if ( (fd = open(path_name, O_RDWR)) < 0) { /* first open file */
+ return fd;
+ }
+ /* set flock structure */
+ lock.l_type = F_UNLCK; /* set type: unlock */
+ lock.l_whence = SEEK_SET; /* start from the beginning of the file */
+ lock.l_start = 0; /* set the start of the locked region */
+ lock.l_len = 0; /* set the length of the locked region */
+ /* do locking */
+ if ( (res = fcntl(fd, F_SETLK, &lock)) < 0 ) {
+ return res;
+ }
+ return 0;
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Il codice delle funzioni che permettono di creare un
+ \textit{mutex} utilizzando il file locking.}
+ \label{fig:ipc_flock_mutex}
+\end{figure}
+
+Il codice per implementare un mutex utilizzando il file locking è riportato in
+\figref{fig:ipc_flock_mutex}; a differenza del precedente caso in cui si sono
+usati i semafori le funzioni questa volta sono sufficienti due funzioni,
+\func{LockMutex} e \func{UnlockMutex}, usate rispettivamente per acquisire e
+rilasciare il mutex.
+
+La prima funzione (\texttt{\small 1--22}) serve per acquisire il mutex.
+Anzitutto si apre (\texttt{\small 9--11}), creandolo se non esiste, il file
+specificato dall'argomento \param{pathname}. In caso di errore si ritorna
+immediatamente, altrimenti si prosegue impostando (\texttt{\small 12--16}) la
+struttura \var{lock} in modo da poter acquisire un write lock sul file. Infine
+si richiede (\texttt{\small 17--20}) il file lock (restituendo il codice di
+ritorno di \func{fcntl} caso di errore). Se il file è libero il lock è
+acquisito e la funzione ritorna immediatamente; altrimenti \func{fcntl} si
+bloccherà (si noti che la si è chiamata con \func{F\_SETLKW}) fino al rilascio
+del lock.
+
+La seconda funzione (\texttt{\small 23--44}) serve a rilasciare il mutex. Di
+nuovo si apre (\texttt{\small 30--33}) il file specificato dall'argomento
+\param{pathname} (che stavolta deve esistere), ritornando immediatamente in
+caso di errore. Poi si passa ad inizializzare (\texttt{\small 34--38}) la
+struttura \var{lock} per il rilascio del lock, che viene effettuato
+(\texttt{\small 39--42}) subito dopo.
+
+ \subsection{Il \textit{memory mapping} anonimo}
+\label{sec:ipc_mmap_anonymous}
+
+Abbiamo già visto che quando i processi sono \textsl{correlati}\footnote{se
+ cioè hanno almeno un progenitore comune.} l'uso delle 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.
+
+Abbiamo visto in \secref{sec:file_memory_map} che è 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
+ nele \textit{memory mapping} anonimo.} Un esempio di utilizzo di questa
+tecnica è mostrato in