+La funzione restituisce il valore di ritorno relativo all'operazione eseguita,
+così come ricavato dalla sottostante \textit{system call} (il numero di byte
+letti, scritti o il valore di ritorno di \func{fsync} o \func{fdatasync}). É
+importante chiamare sempre questa funzione, altrimenti le risorse disponibili
+per le operazioni di I/O asincrono non verrebbero liberate, rischiando di
+arrivare ad un loro esaurimento.
+
+Oltre alle operazioni di lettura e scrittura l'interfaccia POSIX.1b mette a
+disposizione un'altra operazione, quella di sincronizzazione dell'I/O,
+compiuta dalla funzione \funcd{aio\_fsync}, che ha lo stesso effetto della
+analoga \func{fsync}, ma viene eseguita in maniera asincrona; il suo prototipo
+è:
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_fsync(int op, struct aiocb *aiocbp)}
+\fdesc{Richiede la sincronizzazione dei dati su disco.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà gli stessi valori visti \func{aio\_read} con lo
+ stesso significato.
+}
+\end{funcproto}
+
+La funzione richiede la sincronizzazione dei dati delle operazioni di I/O
+relative al file descriptor indicato in \texttt{aiocbp->aio\_fildes},
+ritornando immediatamente. Si tenga presente che la funzione mette
+semplicemente in coda la richiesta, l'esecuzione effettiva della
+sincronizzazione dovrà essere verificata con \func{aio\_error} e
+\func{aio\_return} come per le operazioni di lettura e
+scrittura. L'argomento \param{op} permette di indicare la modalità di
+esecuzione, se si specifica il valore \const{O\_DSYNC} le operazioni saranno
+completate con una chiamata a \func{fdatasync}, se si specifica
+\const{O\_SYNC} con una chiamata a \func{fsync} (per i dettagli vedi
+sez.~\ref{sec:file_sync}).
+
+Il successo della chiamata assicura la richiesta di sincronizzazione dei dati
+relativi operazioni di I/O asincrono richieste fino a quel momento, niente è
+garantito riguardo la sincronizzazione dei dati relativi ad eventuali
+operazioni richieste successivamente. Se si è specificato un meccanismo di
+notifica questo sarà innescato una volta che le operazioni di sincronizzazione
+dei dati saranno completate (\texttt{aio\_sigevent} è l'unico altro campo
+di \param{aiocbp} che viene usato.
+
+In alcuni casi può essere necessario interrompere le operazioni di I/O (in
+genere quando viene richiesta un'uscita immediata dal programma), per questo
+lo standard POSIX.1b prevede una funzione apposita, \funcd{aio\_cancel}, che
+permette di cancellare una operazione richiesta in precedenza; il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_cancel(int fd, struct aiocb *aiocbp)}
+\fdesc{Richiede la cancellazione delle operazioni di I/O asincrono.}
+}
+
+{La funzione ritorna un intero positivo che indica il risultato
+ dell'operazione in caso di successo e $-1$ per un errore, nel qual caso
+ \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] \param{fd} non è un file descriptor valido.
+ \item[\errcode{ENOSYS}] la funzione non è implementata.
+ \end{errlist}
+}
+\end{funcproto}
+
+La funzione permette di cancellare una operazione specifica sul file
+\param{fd}, idicata con \param{aiocbp}, o tutte le operazioni pendenti,
+specificando \val{NULL} come valore di \param{aiocbp}. Quando una operazione
+viene cancellata una successiva chiamata ad \func{aio\_error} riporterà
+\errcode{ECANCELED} come codice di errore, ed mentre il valore di ritorno per
+\func{aio\_return} sarà $-1$, inoltre il meccanismo di notifica non verrà
+invocato. Se con \param{aiocbp} si specifica una operazione relativa ad un
+file descriptor diverso da \param{fd} il risultato è indeterminato. In caso
+di successo, i possibili valori di ritorno per \func{aio\_cancel} (anch'essi
+definiti in \headfile{aio.h}) sono tre:
+\begin{basedescript}{\desclabelwidth{3.0cm}}
+\item[\const{AIO\_ALLDONE}] indica che le operazioni di cui si è richiesta la
+ cancellazione sono state già completate,
+
+\item[\const{AIO\_CANCELED}] indica che tutte le operazioni richieste sono
+ state cancellate,
+
+\item[\const{AIO\_NOTCANCELED}] indica che alcune delle operazioni erano in
+ corso e non sono state cancellate.
+\end{basedescript}
+
+Nel caso si abbia \const{AIO\_NOTCANCELED} occorrerà chiamare
+\func{aio\_error} per determinare quali sono le operazioni effettivamente
+cancellate. Le operazioni che non sono state cancellate proseguiranno il loro
+corso normale, compreso quanto richiesto riguardo al meccanismo di notifica
+del loro avvenuto completamento.
+
+Benché l'I/O asincrono preveda un meccanismo di notifica, l'interfaccia
+fornisce anche una apposita funzione, \funcd{aio\_suspend}, che permette di
+sospendere l'esecuzione del processo chiamante fino al completamento di una
+specifica operazione; il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_suspend(const struct aiocb * const list[], int nent, \\
+\phantom{int aio\_suspend(}const struct timespec *timeout)}
+\fdesc{Attende il completamento di una operazione di I/O asincrono.}
+}
+
+{La funzione ritorna $0$ se una (o più) operazioni sono state completate e
+ $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EAGAIN}] nessuna operazione è stata completata entro
+ \param{timeout}.
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{ENOSYS}] la funzione non è implementata.
+ \end{errlist}
+}
+\end{funcproto}
+
+La funzione permette di bloccare il processo fintanto che almeno una delle
+\param{nent} operazioni specificate nella lista \param{list} è completata, per
+un tempo massimo specificato dalla struttura \struct{timespec} puntata
+da \param{timout}, o fintanto che non arrivi un segnale (si tenga conto che
+questo segnale potrebbe essere anche quello utilizzato come meccanismo di
+notifica). La lista deve essere inizializzata con delle strutture
+\struct{aiocb} relative ad operazioni effettivamente richieste, ma può
+contenere puntatori nulli, che saranno ignorati. In caso si siano specificati
+valori non validi l'effetto è indefinito.
+Un valore \val{NULL} per \param{timout} comporta l'assenza di timeout, mentre
+se si vuole effettuare un \textit{polling} sulle operazioni occorrerà
+specificare un puntatore valido ad una struttura \texttt{timespec} (vedi
+fig.~\ref{fig:sys_timespec_struct}) contenente valori nulli, e verificare poi
+con \func{aio\_error} quale delle operazioni della lista \param{list} è stata
+completata.
+
+Lo standard POSIX.1b infine ha previsto pure una funzione, \funcd{lio\_listio},
+che permette di effettuare la richiesta di una intera lista di operazioni di
+lettura o scrittura; il suo prototipo è:
+
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int lio\_listio(int mode, struct aiocb * const list[], int nent, struct
+ sigevent *sig)}
+
+\fdesc{Richiede l'esecuzione di una serie di operazioni di I/O.}
+}
+
+{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{EAGAIN}] nessuna operazione è stata completata entro
+ \param{timeout}.
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] si è passato un valore di \param{mode} non valido
+ o un numero di operazioni \param{nent} maggiore di
+ \const{AIO\_LISTIO\_MAX}.
+ \item[\errcode{ENOSYS}] la funzione non è implementata.
+ \end{errlist}
+}
+\end{funcproto}
+
+La funzione esegue la richiesta delle \param{nent} operazioni indicate nella
+lista \param{list} un vettore di puntatori a strutture \struct{aiocb}
+indicanti le operazioni da compiere (che verranno eseguite senza un ordine
+particolare). La lista può contenere anche puntatori nulli, che saranno
+ignorati (si possono così eliminare facilmente componenti della lista senza
+doverla rigenerare).
+
+Ciascuna struttura \struct{aiocb} della lista deve contenere un
+\textit{control block} opportunamente inizializzato; in particolare per
+ognuna di esse dovrà essere specificato il tipo di operazione con il campo
+\var{aio\_lio\_opcode}, che può prendere i valori:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\const{LIO\_READ}] si richiede una operazione di lettura.
+\item[\const{LIO\_WRITE}] si richiede una operazione di scrittura.
+\item[\const{LIO\_NOP}] non si effettua nessuna operazione.
+\end{basedescript}
+dove \const{LIO\_NOP} viene usato quando si ha a che fare con un vettore di
+dimensione fissa, per poter specificare solo alcune operazioni, o quando si
+sono dovute cancellare delle operazioni e si deve ripetere la richiesta per
+quelle non completate.
+
+L'argomento \param{mode} controlla il comportamento della funzione, se viene
+usato il valore \const{LIO\_WAIT} la funzione si blocca fino al completamento
+di tutte le operazioni richieste; se si usa \const{LIO\_NOWAIT} la funzione
+ritorna immediatamente dopo aver messo in coda tutte le richieste. In tal caso
+il chiamante può richiedere la notifica del completamento di tutte le
+richieste, impostando l'argomento \param{sig} in maniera analoga a come si fa
+per il campo \var{aio\_sigevent} di \struct{aiocb}.
+
+% TODO: trattare libaio e le system call del kernel per l'I/O asincrono, vedi
+% http://lse.sourceforge.net/io/aio.html,
+% http://webfiveoh.com/content/guides/2012/aug/mon-13th/linux-asynchronous-io-and-libaio.html,
+% https://code.google.com/p/kernel/wiki/AIOUserGuide,
+% http://bert-hubert.blogspot.de/2012/05/on-linux-asynchronous-file-io.html
+
+
+\section{Altre modalità di I/O avanzato}
+\label{sec:file_advanced_io}
+
+Oltre alle precedenti modalità di \textit{I/O multiplexing} e \textsl{I/O
+ asincrono}, esistono altre funzioni che implementano delle modalità di
+accesso ai file più evolute rispetto alle normali funzioni di lettura e
+scrittura che abbiamo esaminato in sez.~\ref{sec:file_unix_interface}. In
+questa sezione allora prenderemo in esame le interfacce per l'\textsl{I/O
+ mappato in memoria}, per l'\textsl{I/O vettorizzato} e altre funzioni di I/O
+avanzato.
+
+
+\subsection{File mappati in memoria}
+\label{sec:file_memory_map}
+
+\itindbeg{memory~mapping}
+Una modalità alternativa di I/O, che usa una interfaccia completamente diversa
+rispetto a quella classica vista in sez.~\ref{sec:file_unix_interface}, è il
+cosiddetto \textit{memory-mapped I/O}, che attraverso il meccanismo della
+\textsl{paginazione} \index{paginazione} usato dalla memoria virtuale (vedi
+sez.~\ref{sec:proc_mem_gen}) permette di \textsl{mappare} il contenuto di un
+file in una sezione dello spazio di indirizzi del processo che lo ha allocato.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=12cm]{img/mmap_layout}
+ \caption{Disposizione della memoria di un processo quando si esegue la
+ mappatura in memoria di un file.}
+ \label{fig:file_mmap_layout}
+\end{figure}
+
+Il meccanismo è illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del
+file viene \textsl{mappata} direttamente nello spazio degli indirizzi del
+programma. Tutte le operazioni di lettura e scrittura su variabili contenute
+in questa zona di memoria verranno eseguite leggendo e scrivendo dal contenuto
+del file attraverso il sistema della memoria virtuale \index{memoria~virtuale}
+che in maniera analoga a quanto avviene per le pagine che vengono salvate e
+rilette nella swap, si incaricherà di sincronizzare il contenuto di quel
+segmento di memoria con quello del file mappato su di esso. Per questo motivo
+si può parlare tanto di \textsl{file mappato in memoria}, quanto di
+\textsl{memoria mappata su file}.
+
+L'uso del \textit{memory-mapping} comporta una notevole semplificazione delle
+operazioni di I/O, in quanto non sarà più necessario utilizzare dei buffer
+intermedi su cui appoggiare i dati da traferire, poiché questi potranno essere
+acceduti direttamente nella sezione di memoria mappata; inoltre questa
+interfaccia è più efficiente delle usuali funzioni di I/O, in quanto permette
+di caricare in memoria solo le parti del file che sono effettivamente usate ad
+un dato istante.
+
+Infatti, dato che l'accesso è fatto direttamente attraverso la
+\index{memoria~virtuale} memoria virtuale, la sezione di memoria mappata su
+cui si opera sarà a sua volta letta o scritta sul file una pagina alla volta e
+solo per le parti effettivamente usate, il tutto in maniera completamente
+trasparente al processo; l'accesso alle pagine non ancora caricate avverrà
+allo stesso modo con cui vengono caricate in memoria le pagine che sono state
+salvate sullo swap.
+
+Infine in situazioni in cui la memoria è scarsa, le pagine che mappano un file
+vengono salvate automaticamente, così come le pagine dei programmi vengono
+scritte sulla swap; questo consente di accedere ai file su dimensioni il cui
+solo limite è quello dello spazio di indirizzi disponibile, e non della
+memoria su cui possono esserne lette delle porzioni.
+
+L'interfaccia POSIX implementata da Linux prevede varie funzioni di sistema
+per la gestione del \textit{memory mapped I/O}, la prima di queste, che serve
+ad eseguire la mappatura in memoria di un file, è \funcd{mmap}; il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{unistd.h}
+\fhead{sys/mman.h}
+\fdecl{void * mmap(void * start, size\_t length, int prot, int flags, int
+ fd, off\_t offset)}
+\fdesc{Esegue la mappatura in memoria di una sezione di un file.}
+}
+
+{La funzione ritorna il puntatore alla zona di memoria mappata in caso di
+ successo, e \const{MAP\_FAILED} ($-1$) per un errore, nel qual caso
+ \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EACCES}] o \param{fd} non si riferisce ad un file regolare,
+ o si è usato \const{MAP\_PRIVATE} ma \param{fd} non è aperto in lettura,
+ o si è usato \const{MAP\_SHARED} e impostato \const{PROT\_WRITE} ed
+ \param{fd} non è aperto in lettura/scrittura, o si è impostato
+ \const{PROT\_WRITE} ed \param{fd} è in \textit{append-only}.
+ \item[\errcode{EAGAIN}] il file è bloccato, o si è bloccata troppa memoria
+ rispetto a quanto consentito dai limiti di sistema (vedi
+ sez.~\ref{sec:sys_resource_limit}).
+ \item[\errcode{EBADF}] il file descriptor non è valido, e non si è usato
+ \const{MAP\_ANONYMOUS}.
+ \item[\errcode{EINVAL}] i valori di \param{start}, \param{length} o
+ \param{offset} non sono validi (o troppo grandi o non allineati sulla
+ dimensione delle pagine).
+ \item[\errcode{ENFILE}] si è superato il limite del sistema sul numero di
+ file aperti (vedi sez.~\ref{sec:sys_resource_limit}).
+ \item[\errcode{ENODEV}] il filesystem di \param{fd} non supporta il memory
+ mapping.
+ \item[\errcode{ENOMEM}] non c'è memoria o si è superato il limite sul
+ numero di mappature possibili.
+ \item[\errcode{EPERM}] l'argomento \param{prot} ha richiesto
+ \const{PROT\_EXEC}, ma il filesystem di \param{fd} è montato con
+ l'opzione \texttt{noexec}.
+ \item[\errcode{ETXTBSY}] si è impostato \const{MAP\_DENYWRITE} ma
+ \param{fd} è aperto in scrittura.
+ \end{errlist}
+}
+\end{funcproto}
+
+
+La funzione richiede di mappare in memoria la sezione del file \param{fd} a
+partire da \param{offset} per \param{length} byte, preferibilmente
+all'indirizzo \param{start}. Il valore \param{start} viene normalmente
+considerato come un suggerimento, ma l'uso di un valore diverso da \val{NULL},
+in cui si rimette completamente al kernel la scelta dell'indirizzo, viene
+sconsigliato per ragioni di portabilità. Il valore di \param{offset} deve
+essere un multiplo della dimensione di una pagina di memoria.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{PROT\_EXEC} & Le pagine possono essere eseguite.\\
+ \const{PROT\_READ} & Le pagine possono essere lette.\\
+ \const{PROT\_WRITE} & Le pagine possono essere scritte.\\
+ \const{PROT\_NONE} & L'accesso alle pagine è vietato.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{prot} di \func{mmap}, relativi alla
+ protezione applicate alle pagine del file mappate in memoria.}
+ \label{tab:file_mmap_prot}
+\end{table}
+
+Il valore dell'argomento \param{prot} indica la protezione\footnote{come
+ accennato in sez.~\ref{sec:proc_memory} in Linux la memoria reale è divisa
+ in pagine, ogni processo vede la sua memoria attraverso uno o più segmenti
+ lineari di memoria virtuale; per ciascuno di questi segmenti il kernel
+ mantiene nella \itindex{page~table} \textit{page table} la mappatura sulle
+ pagine di memoria reale, ed le modalità di accesso (lettura, esecuzione,
+ scrittura); una loro violazione causa quella una \itindex{segment~violation}
+ \textit{segment violation}, e la relativa emissione del segnale
+ \signal{SIGSEGV}.} da applicare al segmento di memoria e deve essere
+specificato come maschera binaria ottenuta dall'OR di uno o più dei valori
+riportati in tab.~\ref{tab:file_mmap_prot}; il valore specificato deve essere
+compatibile con la modalità di accesso con cui si è aperto il file.
+
+L'argomento \param{flags} specifica infine qual è il tipo di oggetto mappato,
+le opzioni relative alle modalità con cui è effettuata la mappatura e alle
+modalità con cui le modifiche alla memoria mappata vengono condivise o
+mantenute private al processo che le ha effettuate. Deve essere specificato
+come maschera binaria ottenuta dall'OR di uno o più dei valori riportati in
+tab.~\ref{tab:file_mmap_flag}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{11cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{MAP\_32BIT} & Esegue la mappatura sui primi 2Gb dello spazio
+ degli indirizzi, viene supportato solo sulle
+ piattaforme \texttt{x86-64} per compatibilità con
+ le applicazioni a 32 bit. Viene ignorato se si è
+ richiesto \const{MAP\_FIXED} (dal 2.4.20).\\
+ \const{MAP\_ANON} & Sinonimo di \const{MAP\_ANONYMOUS}, deprecato.\\
+ \const{MAP\_ANONYMOUS} & La mappatura non è associata a nessun file. Gli
+ argomenti \param{fd} e \param{offset} sono
+ ignorati.\\
+ \const{MAP\_DENYWRITE} & In Linux viene ignorato per evitare
+ \textit{DoS} \itindex{Denial~of~Service~(DoS)}
+ (veniva usato per segnalare che tentativi di
+ scrittura sul file dovevano fallire con
+ \errcode{ETXTBSY}).\\
+ \const{MAP\_EXECUTABLE}& Ignorato.\\
+ \const{MAP\_FILE} & Valore di compatibilità, ignorato.\\
+ \const{MAP\_FIXED} & Non permette di restituire un indirizzo diverso
+ da \param{start}, se questo non può essere usato
+ \func{mmap} fallisce. Se si imposta questo flag il
+ valore di \param{start} deve essere allineato
+ alle dimensioni di una pagina.\\
+ \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} \textit{stack}.
+ Indica che la mappatura deve essere effettuata
+ con gli indirizzi crescenti verso il basso.\\
+ \const{MAP\_HUGETLB} & Esegue la mappatura usando le cosiddette
+ ``\textit{huge pages}'' (dal 2.6.32).\\
+ \const{MAP\_LOCKED} & Se impostato impedisce lo swapping delle pagine
+ mappate (dal 2.5.37).\\
+ \const{MAP\_NONBLOCK} & Esegue un \textit{prefaulting} più limitato che
+ non causa I/O (dal 2.5.46).\\
+ \const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva
+ delle pagine di swap ad uso del meccanismo del
+ \textit{copy on write} \itindex{copy~on~write}
+ per mantenere le modifiche fatte alla regione
+ mappata, in questo caso dopo una scrittura, se
+ non c'è più memoria disponibile, si ha
+ l'emissione di un \signal{SIGSEGV}.\\
+ \const{MAP\_PRIVATE} & I cambiamenti sulla memoria mappata non vengono
+ riportati sul file. Ne viene fatta una copia
+ privata cui solo il processo chiamante ha
+ accesso. Le modifiche sono mantenute attraverso
+ il meccanismo del \textit{copy on write} e
+ salvate su swap in caso di necessità. Non è
+ specificato se i cambiamenti sul file originale
+ vengano riportati sulla regione
+ mappata. Incompatibile con \const{MAP\_SHARED}.\\
+ \const{MAP\_POPULATE} & Esegue il \itindex{prefaulting}
+ \textit{prefaulting} delle pagine di memoria
+ necessarie alla mappatura (dal 2.5.46).\\
+ \const{MAP\_SHARED} & I cambiamenti sulla memoria mappata vengono
+ riportati sul file e saranno immediatamente
+ visibili agli altri processi che mappano lo stesso
+ file.\footnotemark Il file su disco però non sarà
+ aggiornato fino alla chiamata di \func{msync} o
+ \func{munmap}), e solo allora le modifiche saranno
+ visibili per l'I/O convenzionale. Incompatibile
+ con \const{MAP\_PRIVATE}.\\
+ \const{MAP\_STACK} & da trattare (dal 2.6.27).\\
+ \const{MAP\_UNINITIALIZED}& da trattare (dal 2.6.33).\\
+% \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
+% mappata con \func{mremap}, proposto ma pare non
+% implementato.\\
+ \hline
+ \end{tabular}
+ \caption{Valori possibili dell'argomento \param{flag} di \func{mmap}.}
+ \label{tab:file_mmap_flag}
+\end{table}
+
+\footnotetext{l'uso di questo flag con \const{MAP\_SHARED} è stato
+ implementato in Linux a partire dai kernel della serie 2.4.x; esso consente
+ di creare segmenti di memoria condivisa e torneremo sul suo utilizzo in
+ sez.~\ref{sec:ipc_mmap_anonymous}.}
+
+% TODO trattare MAP_HUGETLB introdotto con il kernel 2.6.32, e modifiche
+% introdotte con il 3.8 per le dimensioni variabili delle huge pages
+
+Gli effetti dell'accesso ad una zona di memoria mappata su file possono essere
+piuttosto complessi, essi si possono comprendere solo tenendo presente che
+tutto quanto è comunque basato sul meccanismo della \index{memoria~virtuale}
+memoria virtuale. Questo comporta allora una serie di conseguenze. La più
+ovvia è che se si cerca di scrivere su una zona mappata in sola lettura si
+avrà l'emissione di un segnale di violazione di accesso (\signal{SIGSEGV}),
+dato che i permessi sul segmento di memoria relativo non consentono questo
+tipo di accesso.
+
+È invece assai diversa la questione relativa agli accessi al di fuori della
+regione di cui si è richiesta la mappatura. A prima vista infatti si potrebbe
+ritenere che anch'essi debbano generare un segnale di violazione di accesso;
+questo però non tiene conto del fatto che, essendo basata sul meccanismo della
+\index{paginazione} paginazione, la mappatura in memoria non può che essere
+eseguita su un segmento di dimensioni rigorosamente multiple di quelle di una
+pagina, ed in generale queste potranno non corrispondere alle dimensioni
+effettive del file o della sezione che si vuole mappare.
+
+\begin{figure}[!htb]
+ \centering
+ \includegraphics[height=6cm]{img/mmap_boundary}
+ \caption{Schema della mappatura in memoria di una sezione di file di
+ dimensioni non corrispondenti al bordo di una pagina.}
+ \label{fig:file_mmap_boundary}
+\end{figure}
+
+Il caso più comune è quello illustrato in fig.~\ref{fig:file_mmap_boundary},
+in cui la sezione di file non rientra nei confini di una pagina: in tal caso
+verrà il file sarà mappato su un segmento di memoria che si estende fino al
+bordo della pagina successiva.
+
+In questo caso è possibile accedere a quella zona di memoria che eccede le
+dimensioni specificate da \param{length}, senza ottenere un \signal{SIGSEGV}
+poiché essa è presente nello spazio di indirizzi del processo, anche se non è
+mappata sul file. Il comportamento del sistema è quello di restituire un
+valore nullo per quanto viene letto, e di non riportare su file quanto viene
+scritto.
+
+Un caso più complesso è quello che si viene a creare quando le dimensioni del
+file mappato sono più corte delle dimensioni della mappatura, oppure quando il
+file è stato troncato, dopo che è stato mappato, ad una dimensione inferiore a
+quella della mappatura in memoria.
+
+In questa situazione, per la sezione di pagina parzialmente coperta dal
+contenuto del file, vale esattamente quanto visto in precedenza; invece per la
+parte che eccede, fino alle dimensioni date da \param{length}, l'accesso non
+sarà più possibile, ma il segnale emesso non sarà \signal{SIGSEGV}, ma
+\signal{SIGBUS}, come illustrato in fig.~\ref{fig:file_mmap_exceed}.
+
+Non tutti i file possono venire mappati in memoria, dato che, come illustrato
+in fig.~\ref{fig:file_mmap_layout}, la mappatura introduce una corrispondenza
+biunivoca fra una sezione di un file ed una sezione di memoria. Questo
+comporta che ad esempio non è possibile mappare in memoria file descriptor
+relativi a \textit{pipe}, socket e \textit{fifo}, per i quali non ha senso
+parlare di \textsl{sezione}. Lo stesso vale anche per alcuni file di
+dispositivo, che non dispongono della relativa operazione \func{mmap} (si
+ricordi quanto esposto in sez.~\ref{sec:file_vfs_work}). Si tenga presente
+però che esistono anche casi di dispositivi (un esempio è l'interfaccia al
+ponte PCI-VME del chip Universe) che sono utilizzabili solo con questa
+interfaccia.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[height=6cm]{img/mmap_exceed}
+ \caption{Schema della mappatura in memoria di file di dimensioni inferiori
+ alla lunghezza richiesta.}
+ \label{fig:file_mmap_exceed}
+\end{figure}
+
+Dato che passando attraverso una \func{fork} lo spazio di indirizzi viene
+copiato integralmente, i file mappati in memoria verranno ereditati in maniera
+trasparente dal processo figlio, mantenendo gli stessi attributi avuti nel
+padre; così se si è usato \const{MAP\_SHARED} padre e figlio accederanno allo
+stesso file in maniera condivisa, mentre se si è usato \const{MAP\_PRIVATE}
+ciascuno di essi manterrà una sua versione privata indipendente. Non c'è
+invece nessun passaggio attraverso una \func{exec}, dato che quest'ultima
+sostituisce tutto lo spazio degli indirizzi di un processo con quello di un
+nuovo programma.
+
+Quando si effettua la mappatura di un file vengono pure modificati i tempi ad
+esso associati (di cui si è trattato in sez.~\ref{sec:file_file_times}). Il
+valore di \var{st\_atime} può venir cambiato in qualunque istante a partire
+dal momento in cui la mappatura è stata effettuata: il primo riferimento ad
+una pagina mappata su un file aggiorna questo tempo. I valori di
+\var{st\_ctime} e \var{st\_mtime} possono venir cambiati solo quando si è
+consentita la scrittura sul file (cioè per un file mappato con
+\const{PROT\_WRITE} e \const{MAP\_SHARED}) e sono aggiornati dopo la scrittura
+o in corrispondenza di una eventuale \func{msync}.
+
+Dato per i file mappati in memoria le operazioni di I/O sono gestite
+direttamente dalla \index{memoria~virtuale} memoria virtuale, occorre essere
+consapevoli delle interazioni che possono esserci con operazioni effettuate
+con l'interfaccia dei file di sez.~\ref{sec:file_unix_interface}. Il problema
+è che una volta che si è mappato un file, le operazioni di lettura e scrittura
+saranno eseguite sulla memoria, e riportate su disco in maniera autonoma dal
+sistema della memoria virtuale.
+
+Pertanto se si modifica un file con l'interfaccia standard queste modifiche
+potranno essere visibili o meno a seconda del momento in cui la memoria
+virtuale trasporterà dal disco in memoria quella sezione del file, perciò è
+del tutto imprevedibile il risultato della modifica di un file nei confronti
+del contenuto della memoria su cui è mappato.
+
+Per questo, è sempre sconsigliabile eseguire scritture su file attraverso
+l'interfaccia standard quando lo si è mappato in memoria, è invece possibile
+usare l'interfaccia standard per leggere un file mappato in memoria, purché si
+abbia una certa cura; infatti l'interfaccia dell'I/O mappato in memoria mette
+a disposizione la funzione \funcd{msync} per sincronizzare il contenuto della
+memoria mappata con il file su disco; il suo prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{sys/mman.h}