Reindicizzazioni.
[gapil.git] / fileadv.tex
index 1c7f147ef5d1d06b0a53b698caeb64126179894a..caab10082b300693aa1bb850c9ea980f54e6676c 100644 (file)
@@ -1,6 +1,6 @@
 %% fileadv.tex
 %%
-%% Copyright (C) 2000-2014 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2015 Simone Piccardi.  Permission is granted to
 %% copy, distribute and/or modify this document under the terms of the GNU Free
 %% Documentation License, Version 1.1 or any later version published by the
 %% Free Software Foundation; with the Invariant Sections being "Un preambolo",
@@ -8,6 +8,7 @@
 %% license is included in the section entitled "GNU Free Documentation
 %% License".
 %%
+
 \chapter{La gestione avanzata dei file}
 \label{cha:file_advanced}
 In questo capitolo affronteremo le tematiche relative alla gestione avanzata
@@ -28,9 +29,9 @@ controllo più dettagliato delle modalità di I/O.
 In sez.~\ref{sec:file_shared_access} abbiamo preso in esame le modalità in cui
 un sistema unix-like gestisce l'accesso concorrente ai file da parte di
 processi diversi. In quell'occasione si è visto come, con l'eccezione dei file
-aperti in \itindex{append~mode} \textit{append mode}, quando più processi
-scrivono contemporaneamente sullo stesso file non è possibile determinare la
-sequenza in cui essi opereranno.
+aperti in \textit{append mode}, quando più processi scrivono
+contemporaneamente sullo stesso file non è possibile determinare la sequenza
+in cui essi opereranno.
 
 Questo causa la possibilità di una \itindex{race~condition} \textit{race
   condition}; in generale le situazioni più comuni sono due: l'interazione fra
@@ -3493,10 +3494,6 @@ raggruppati in un solo evento.
 \subsection{L'interfaccia POSIX per l'I/O asincrono}
 \label{sec:file_asyncronous_io}
 
-% vedere anche http://davmac.org/davpage/linux/async-io.html  e
-% http://www.ibm.com/developerworks/linux/library/l-async/ 
-
-
 Una modalità alternativa all'uso dell'\textit{I/O multiplexing} per gestione
 dell'I/O simultaneo su molti file è costituita dal cosiddetto \textsl{I/O
   asincrono} o ``AIO''. Il concetto base dell'\textsl{I/O asincrono} è che le
@@ -3505,26 +3502,27 @@ ritornare, così che il processo non viene bloccato.  In questo modo diventa ad
 esempio possibile effettuare una richiesta preventiva di dati, in modo da
 poter effettuare in contemporanea le operazioni di calcolo e quelle di I/O.
 
-Benché la modalità di apertura asincrona di un file possa risultare utile in
-varie occasioni (in particolar modo con i socket e gli altri file per i quali
-le funzioni di I/O sono \index{system~call~lente} \textit{system call} lente),
-essa è comunque limitata alla notifica della disponibilità del file descriptor
-per le operazioni di I/O, e non ad uno svolgimento asincrono delle medesime.
-Lo standard POSIX.1b definisce una interfaccia apposita per l'I/O asincrono
-vero e proprio,\footnote{questa è stata ulteriormente perfezionata nelle
-  successive versioni POSIX.1-2001 e POSIX.1-2008.} che prevede un insieme di
-funzioni dedicate per la lettura e la scrittura dei file, completamente
-separate rispetto a quelle usate normalmente.
+Benché la modalità di apertura asincrona di un file vista in
+sez.~\ref{sec:signal_driven_io} possa risultare utile in varie occasioni (in
+particolar modo con i socket e gli altri file per i quali le funzioni di I/O
+sono \index{system~call~lente} \textit{system call} lente), essa è comunque
+limitata alla notifica della disponibilità del file descriptor per le
+operazioni di I/O, e non ad uno svolgimento asincrono delle medesime.  Lo
+standard POSIX.1b definisce una interfaccia apposita per l'I/O asincrono vero
+e proprio,\footnote{questa è stata ulteriormente perfezionata nelle successive
+  versioni POSIX.1-2001 e POSIX.1-2008.} che prevede un insieme di funzioni
+dedicate per la lettura e la scrittura dei file, completamente separate
+rispetto a quelle usate normalmente.
 
 In generale questa interfaccia è completamente astratta e può essere
-implementata sia direttamente nel kernel, che in user space attraverso l'uso
-di \itindex{thread} \textit{thread}. Per le versioni del kernel meno recenti
+implementata sia direttamente nel kernel che in user space attraverso l'uso di
+\itindex{thread} \textit{thread}. Per le versioni del kernel meno recenti
 esiste una implementazione di questa interfaccia fornita completamente delle
 \acr{glibc} a partire dalla versione 2.1, che è realizzata completamente in
 user space, ed è accessibile linkando i programmi con la libreria
-\file{librt}. Nelle versioni più recenti (a partire dalla 2.5.32) è stato
-introdotto nel kernel un nuovo layer per l'I/O asincrono, ma ancora il
-supporto è parziale ed insufficiente ad implementare l'AIO POSIX. 
+\file{librt}. A partire dalla versione 2.5.32 è stato introdotto nel kernel
+una nuova infrastruttura per l'I/O asincrono, ma ancora il supporto è parziale
+ed insufficiente ad implementare tutto l'AIO POSIX.
 
 Lo standard POSIX prevede che tutte le operazioni di I/O asincrono siano
 controllate attraverso l'uso di una apposita struttura \struct{aiocb} (il cui
@@ -3560,16 +3558,16 @@ l'indirizzo del buffer usato per l'I/O, ed in \var{aio\_nbytes} la lunghezza
 del blocco di dati da trasferire.
 
 Il campo \var{aio\_reqprio} permette di impostare la priorità delle operazioni
-di I/O.\footnote{in generale perché ciò sia possibile occorre che la
-  piattaforma supporti questa caratteristica, questo viene indicato definendo
-  le macro \macro{\_POSIX\_PRIORITIZED\_IO}, e
-  \macro{\_POSIX\_PRIORITY\_SCHEDULING}.} La priorità viene impostata a
-partire da quella del processo chiamante (vedi sez.~\ref{sec:proc_priority}),
-cui viene sottratto il valore di questo campo.  Il campo
-\var{aio\_lio\_opcode} è usato solo dalla funzione \func{lio\_listio}, che,
-come vedremo, permette di eseguire con una sola chiamata una serie di
-operazioni, usando un vettore di \textit{control block}. Tramite questo campo
-si specifica quale è la natura di ciascuna di esse.
+di I/O, in generale perché ciò sia possibile occorre che la piattaforma
+supporti questa caratteristica, questo viene indicato dal fatto che le macro
+\macro{\_POSIX\_PRIORITIZED\_IO}, e \macro{\_POSIX\_PRIORITY\_SCHEDULING} sono
+definite. La priorità viene impostata a partire da quella del processo
+chiamante (vedi sez.~\ref{sec:proc_priority}), cui viene sottratto il valore
+di questo campo.  Il campo \var{aio\_lio\_opcode} è usato solo dalla funzione
+\func{lio\_listio}, che, come vedremo, permette di eseguire con una sola
+chiamata una serie di operazioni, usando un vettore di \textit{control
+  block}. Tramite questo campo si specifica quale è la natura di ciascuna di
+esse.
 
 Infine il campo \var{aio\_sigevent} è una struttura di tipo \struct{sigevent}
 (illustrata in in fig.~\ref{fig:struct_sigevent}) che serve a specificare il
@@ -3579,7 +3577,7 @@ stessa si veda quanto già visto in proposito in sez.~\ref{sec:sig_timer_adv}.
 
 Le due funzioni base dell'interfaccia per l'I/O asincrono sono
 \funcd{aio\_read} ed \funcd{aio\_write}.  Esse permettono di richiedere una
-lettura od una scrittura asincrona di dati, usando la struttura \struct{aiocb}
+lettura od una scrittura asincrona di dati usando la struttura \struct{aiocb}
 appena descritta; i rispettivi prototipi sono:
 
 \begin{funcproto}{
@@ -3593,11 +3591,11 @@ appena descritta; i rispettivi prototipi sono:
 {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}] la coda delle richieste è momentaneamente piena.
   \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato.
-  \item[\errcode{ENOSYS}] la funzione non è implementata.
   \item[\errcode{EINVAL}] si è specificato un valore non valido per i campi
     \var{aio\_offset} o \var{aio\_reqprio} di \param{aiocbp}.
-  \item[\errcode{EAGAIN}] la coda delle richieste è momentaneamente piena.
+  \item[\errcode{ENOSYS}] la funzione non è implementata.
   \end{errlist}
 }
 \end{funcproto}
@@ -3608,16 +3606,15 @@ richiesta, o in caso di errore. Non è detto che gli errori \errcode{EBADF} ed
 \errcode{EINVAL} siano rilevati immediatamente al momento della chiamata,
 potrebbero anche emergere nelle fasi successive delle operazioni. Lettura e
 scrittura avvengono alla posizione indicata da \var{aio\_offset}, a meno che
-il file non sia stato aperto in \itindex{append~mode} \textit{append mode}
-(vedi sez.~\ref{sec:file_open_close}), nel qual caso le scritture vengono
-effettuate comunque alla fine de file, nell'ordine delle chiamate a
-\func{aio\_write}.
+il file non sia stato aperto in \textit{append mode} (vedi
+sez.~\ref{sec:file_open_close}), nel qual caso le scritture vengono effettuate
+comunque alla fine del file, nell'ordine delle chiamate a \func{aio\_write}.
 
 Si tenga inoltre presente che deallocare la memoria indirizzata da
 \param{aiocbp} o modificarne i valori prima della conclusione di una
 operazione può dar luogo a risultati impredicibili, perché l'accesso ai vari
 campi per eseguire l'operazione può avvenire in un momento qualsiasi dopo la
-richiesta.  Questo comporta che non si devono usare per \param{aiocbp}
+richiesta. Questo comporta che non si devono usare per \param{aiocbp}
 \index{variabili!automatiche} variabili automatiche e che non si deve
 riutilizzare la stessa struttura per un'altra operazione fintanto che la
 precedente non sia stata ultimata. In generale per ogni operazione si deve
@@ -3629,111 +3626,133 @@ eseguite in maniera corretta; per verificarne l'esito l'interfaccia prevede
 altre due funzioni, che permettono di controllare lo stato di esecuzione. La
 prima è \funcd{aio\_error}, che serve a determinare un eventuale stato di
 errore; il suo prototipo è:
-\begin{prototype}{aio.h}
-  {int aio\_error(const struct aiocb *aiocbp)}  
 
-  Determina lo stato di errore delle operazioni di I/O associate a
-  \param{aiocbp}.
-  
-  \bodydesc{La funzione restituisce 0 se le operazioni si sono concluse con
-    successo, altrimenti restituisce il codice di errore relativo al loro
-    fallimento.}
-\end{prototype}
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_error(const struct aiocb *aiocbp)} 
+\fdesc{Determina lo stato di errore di una operazione di I/O asincrono.} 
+}
 
-Se l'operazione non si è ancora completata viene restituito l'errore di
-\errcode{EINPROGRESS}. La funzione ritorna zero quando l'operazione si è
+{La funzione ritorna $0$ se le operazioni si sono concluse con successo,
+  altrimenti restituisce \errval{EINPROGRESS} se non sono concluse,
+  \errcode{ECANCELED} se sono state cancellate o il relativo codice di errore
+  se sono fallite.}
+\end{funcproto}
+
+Se l'operazione non si è ancora completata viene sempre restituito l'errore di
+\errcode{EINPROGRESS}, mentre se è stata cancellata ritorna
+\errcode{ECANCELED}. La funzione ritorna zero quando l'operazione si è
 conclusa con successo, altrimenti restituisce il codice dell'errore
 verificatosi, ed esegue la corrispondente impostazione di \var{errno}. Il
 codice può essere sia \errcode{EINVAL} ed \errcode{EBADF}, dovuti ad un valore
 errato per \param{aiocbp}, che uno degli errori possibili durante l'esecuzione
 dell'operazione di I/O richiesta, nel qual caso saranno restituiti, a seconda
 del caso, i codici di errore delle \textit{system call} \func{read},
-\func{write} e \func{fsync}.
+\func{write}, \func{fsync} e \func{fdatasync}.
 
 Una volta che si sia certi che le operazioni siano state concluse (cioè dopo
 che una chiamata ad \func{aio\_error} non ha restituito
 \errcode{EINPROGRESS}), si potrà usare la funzione \funcd{aio\_return}, che
 permette di verificare il completamento delle operazioni di I/O asincrono; il
 suo prototipo è:
-\begin{prototype}{aio.h}
-{ssize\_t aio\_return(const struct aiocb *aiocbp)} 
 
-Recupera il valore dello stato di ritorno delle operazioni di I/O associate a
-\param{aiocbp}.
-  
-\bodydesc{La funzione restituisce lo stato di uscita dell'operazione
-  eseguita.}
-\end{prototype}
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{ssize\_t aio\_return(const struct aiocb *aiocbp)}
+\fdesc{Ottiene lo stato dei risultati di una operazione di I/O asincrono.} 
+}
 
-La funzione deve essere chiamata una sola volte per ciascuna operazione
-asincrona, essa infatti fa sì che il sistema rilasci le risorse ad essa
-associate. É per questo motivo che occorre chiamare la funzione solo dopo che
-l'operazione cui \param{aiocbp} fa riferimento si è completata. Una chiamata
-precedente il completamento delle operazioni darebbe risultati indeterminati.
+{La funzione ritorna lo stato di uscita dell'operazione eseguita (il valore
+  che avrebbero restituito le equivalenti funzioni eseguite in maniera
+  sincrona).}
+\end{funcproto}
+
+La funzione recupera il valore dello stato di ritorno delle operazioni di I/O
+associate a \param{aiocbp} e deve essere chiamata una sola volta per ciascuna
+operazione asincrona, essa infatti fa sì che il sistema rilasci le risorse ad
+essa associate. É per questo motivo che occorre chiamare la funzione solo dopo
+che l'operazione cui \param{aiocbp} fa riferimento si è completata
+verificandolo con \func{aio\_error}, ed usarla una sola volta. Una chiamata
+precedente il completamento delle operazioni darebbe risultati indeterminati,
+così come chiamarla più di una volta.
 
 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}).  É 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.
+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{prototype}{aio.h}
-{int aio\_fsync(int op, struct aiocb *aiocbp)} 
 
-Richiede la sincronizzazione dei dati per il file indicato da \param{aiocbp}.
-  
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
-  errore, che può essere, con le stesse modalità di \func{aio\_read},
-  \errval{EAGAIN}, \errval{EBADF} o \errval{EINVAL}.}
-\end{prototype}
-
-La funzione richiede la sincronizzazione delle operazioni di I/O, ritornando
-immediatamente. 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}).
+\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}
 
-Il successo della chiamata assicura la sincronizzazione delle operazioni fino
-allora richieste, 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.
+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}).
 
-In alcuni casi può essere necessario interrompere le operazioni (in genere
-quando viene richiesta un'uscita immediata dal programma), per questo lo
-standard POSIX.1b prevede una funzione apposita, \funcd{aio\_cancel}, che
+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{prototype}{aio.h}
-{int aio\_cancel(int fildes, struct aiocb *aiocbp)} 
 
-Richiede la cancellazione delle operazioni sul file \param{fildes} specificate
-da \param{aiocbp}.
-  
-\bodydesc{La funzione restituisce il risultato dell'operazione con un codice
-  di positivo, e -1 in caso di errore, che avviene qualora si sia specificato
-  un valore non valido di \param{fildes}, imposta \var{errno} al valore
-  \errval{EBADF}.}
-\end{prototype}
+\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{fildes}, 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 il suo codice di ritorno sarà -1, inoltre il meccanismo
-di notifica non verrà invocato. Se si specifica una operazione relativa ad un
-altro file descriptor 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:
+\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,
@@ -3755,73 +3774,88 @@ 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{prototype}{aio.h}
-{int aio\_suspend(const struct aiocb * const list[], int nent, const struct
-    timespec *timeout)}
-  
-  Attende, per un massimo di \param{timeout}, il completamento di una delle
-  operazioni specificate da \param{list}.
-  
-  \bodydesc{La funzione restituisce 0 se una (o più) operazioni sono state
-    completate, e -1 in caso di errore nel qual caso \var{errno} assumerà uno
-    dei valori:
-    \begin{errlist}
+
+\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{ENOSYS}] la funzione non è implementata.
     \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
-    \end{errlist}
-  }
-\end{prototype}
-
+    \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 da \param{timout}, o fintanto che non arrivi un
-segnale.\footnote{si tenga conto che questo segnale può anche essere 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.
+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{prototype}{aio.h}
-  {int lio\_listio(int mode, struct aiocb * const list[], int nent, struct
+
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int lio\_listio(int mode, struct aiocb * const list[], int nent, struct
     sigevent *sig)}
-  
-  Richiede l'esecuzione delle operazioni di I/O elencata da \param{list},
-  secondo la modalità \param{mode}.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
-    errore, nel qual caso \var{errno} assumerà uno dei valori:
-    \begin{errlist}
+
+\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.
-    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
-    \end{errlist}
-  }
-\end{prototype}
+  \end{errlist}
+}
+\end{funcproto}
 
 La funzione esegue la richiesta delle \param{nent} operazioni indicate nella
-lista \param{list} che deve contenere gli indirizzi di altrettanti
-\textit{control block} opportunamente inizializzati; in particolare dovrà
-essere specificato il tipo di operazione con il campo \var{aio\_lio\_opcode},
-che può prendere i valori:
+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.
+na 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.
+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
@@ -3856,9 +3890,9 @@ avanzato.
 \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
+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
+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]
@@ -3873,12 +3907,12 @@ 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}.
+del file attraverso il sistema della memoria virtuale illustrato in
+sez.~\ref{sec:proc_mem_gen} che in maniera analoga a quanto avviene per le
+pagine che vengono salvate e rilette nella \textit{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
@@ -3894,64 +3928,73 @@ 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.
+salvate sullo \textit{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
+scritte sulla \textit{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 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{functions}
-  
-  \headdecl{unistd.h}
-  \headdecl{sys/mman.h} 
+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 è:
 
-  \funcdecl{void * mmap(void * start, size\_t length, int prot, int flags, int
+\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)}
-  
-  Esegue la mappatura in memoria della sezione specificata del file \param{fd}.
-  
-  \bodydesc{La funzione restituisce il puntatore alla zona di memoria mappata
-    in caso di successo, e \const{MAP\_FAILED} (-1) in caso di errore, nel
-    qual caso \var{errno} assumerà uno dei valori:
-    \begin{errlist}
-    \item[\errcode{EBADF}] il file descriptor non è valido, e non si è usato
-      \const{MAP\_ANONYMOUS}.
+\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} (\texttt{(void *) -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{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{ETXTBSY}] si è impostato \const{MAP\_DENYWRITE} ma
-      \param{fd} è aperto in scrittura.
     \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{ENOMEM}] non c'è memoria o si è superato il limite sul
-      numero di mappature possibili.
+    \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), o \param{lengh} è zero (solo dal 2.6.12)
+      o \param{flags} contiene sia \const{MAP\_PRIVATE} che
+      \const{MAP\_SHARED} o nessuno dei due.
+    \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{EOVERFLOW}] su architettura a 32 bit con il supporto per i
+      \textit{large file} (che hanno una dimensione a 64 bit) il numero di
+      pagine usato per \param{lenght} aggiunto a quello usato
+      per \param{offset} eccede i 32 bit (\texttt{unsigned long}).
     \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{ENFILE}] si è superato il limite del sistema sul numero di
-      file aperti (vedi sez.~\ref{sec:sys_resource_limit}).
-    \end{errlist}
-  }
-\end{functions}
+    \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 di \param{offset} deve essere un
-multiplo della dimensione di una pagina di memoria. 
+all'indirizzo \param{start}. Il valore \param{start} viene normalmente
+considerato come un suggerimento, ma l'uso di un qualunque 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
@@ -3974,25 +4017,18 @@ multiplo della dimensione di una pagina di memoria.
 
 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]
+  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 \textit{page table} la mappatura sulle pagine di memoria
+  reale, ed le modalità di accesso (lettura, esecuzione, scrittura); una loro
+  violazione causa quella una \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.
+
+\begin{table}[!htb]
   \centering
   \footnotesize
   \begin{tabular}[c]{|l|p{11cm}|}
@@ -4000,105 +4036,139 @@ tab.~\ref{tab:file_mmap_flag}.
     \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 kernel 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. L'uso di questo flag con
+                             \const{MAP\_SHARED} è stato implementato in Linux
+                             a partire dai kernel della serie 2.4.x.\\
+    \const{MAP\_DENYWRITE} & In Linux viene ignorato per evitare
+                             \textit{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 \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 kernel 2.6.32).\\
+    \const{MAP\_LOCKED}    & Se impostato impedisce lo \textit{swapping} delle
+                             pagine mappate (dal kernel 2.5.37).\\
+    \const{MAP\_NONBLOCK}  & Esegue un \textit{prefaulting} più limitato che
+                             non causa I/O (dal kernel 2.5.46).\\
+    \const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva
+                             delle pagine di \textit{swap} ad uso del meccanismo
+                             del \textit{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\_POPULATE}  & Esegue il \textit{prefaulting} delle pagine di
+                             memoria necessarie alla mappatura (dal kernel
+                             2.5.46).\\ 
+    \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.  Incompatibile con \const{MAP\_SHARED}.\\
     \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
+                             file. Incompatibile
                              con \const{MAP\_PRIVATE}.\\ 
-    \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} \itindex{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\_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\_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\_LOCKED}    & Se impostato impedisce lo swapping delle pagine
-                             mappate.\\
-    \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\_ANONYMOUS} & La mappatura non è associata a nessun file. Gli
-                             argomenti \param{fd} e \param{offset} sono
-                             ignorati.\footnotemark\\
-    \const{MAP\_ANON}      & Sinonimo di \const{MAP\_ANONYMOUS}, deprecato.\\
-    \const{MAP\_FILE}      & Valore di compatibilità, ignorato.\\
-    \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}.\\
-    \const{MAP\_POPULATE}  & Esegue il \itindex{prefaulting}
-                             \textit{prefaulting} delle pagine di memoria
-                             necessarie alla mappatura.\\
-    \const{MAP\_NONBLOCK}  & Esegue un \textit{prefaulting} più limitato che
-                             non causa I/O.\footnotemark\\
+    \const{MAP\_STACK}     & Al momento è ignorato, è stato fornito (dal kernel
+                             2.6.27) a supporto della implementazione dei
+                             thread nelle \acr{glibc}, per allocare memoria in
+                             uno spazio utilizzabile come \textit{stack} per le
+                             architetture hardware che richiedono un
+                             trattamento speciale di quest'ultimo.\\
+    \const{MAP\_UNINITIALIZED}& Specifico per i sistemi embedded ed
+                             utilizzabile dal kernel 2.6.33 solo se è stata
+                             abilitata in fase di compilazione dello stesso
+                             l'opzione
+                             \texttt{CONFIG\_MMAP\_ALLOW\_UNINITIALIZED}. Se
+                             usato le pagine di memoria usate nella mappatura
+                             anonima non vengono cancellate; questo migliora
+                             le prestazioni sui sistemi con risorse minime, ma
+                             comporta la possibilità di rileggere i dati di
+                             altri processi che han chiuso una mappatura, per
+                             cui viene usato solo quando (come si suppone sia
+                             per i sistemi embedded) si ha il completo
+                             controllo dell'uso della memoria da parte degli
+                             utenti.\\ 
 %     \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
 %                              mappata con \func{mremap}, proposto ma pare non
 %                              implementato.\\
-%     \const{MAP\_HUGETLB}& da trattare.\\
-% 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
-
     \hline
   \end{tabular}
   \caption{Valori possibili dell'argomento \param{flag} di \func{mmap}.}
   \label{tab:file_mmap_flag}
 \end{table}
 
-\footnotetext[68]{dato che tutti faranno riferimento alle stesse pagine di
-  memoria.}  
-
-\footnotetext[69]{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
 
-\footnotetext{questo flag ed il precedente \const{MAP\_POPULATE} sono stati
-  introdotti nel kernel 2.5.46 insieme alla mappatura non lineare di cui
-  parleremo più avanti.}
+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}. Fra questi comunque deve sempre essere
+specificato o \const{MAP\_PRIVATE} o \const{MAP\_SHARED} per indicare la
+modalità con cui viene effettuata la mappatura.
+
+Esistono infatti due modalità alternative di eseguire la mappatura di un file;
+la più comune è \const{MAP\_SHARED} in cui la memoria è condivisa e le
+modifiche effettuate su di essa sono visibili a tutti i processi che hanno
+mappato lo stesso file. In questo caso le modifiche vengono anche riportate su
+disco, anche se questo può non essere immediato a causa della bufferizzazione:
+si potrà essere sicuri dell'aggiornamento solo in seguito alla chiamata di
+\func{msync} o \func{munmap}, e solo allora le modifiche saranno visibili sul
+file con l'I/O convenzionale.
+
+Con \const{MAP\_PRIVATE} invece viene creata una copia privata del file,
+questo non viene mai modificato e solo il processo chiamante ha accesso alla
+mappatura. Le modifiche eseguite dal processo sulla mappatura vengono
+effettuate utilizzando il meccanismo del \textit{copy on write}, mentenute in
+memoria e salvate su \textit{swap} in caso di necessità.  Non è specificato se
+i cambiamenti sul file originale vengano riportati sulla regione mappata.
+
+Gli altri valori di \func{flag} modificano le caratteristiche della
+mappatura. Fra questi il più rilevante è probabilmente \const{MAP\_ANONYMOUS}
+che consente di creare segmenti di memoria condivisa fra processi diversi
+senza appoggiarsi a nessun file (torneremo sul suo utilizzo in
+sez.~\ref{sec:ipc_mmap_anonymous}). In tal caso gli argomenti \param{fd}
+e \param{offset} vangono ignorati, anche se alcune implementazioni richiedono
+che invece \param{fd} sia $-1$, convenzione che è opportuno seguire se si ha a
+cuore la portabilità dei programmi.
 
 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.
+tutto quanto è comunque basato sul meccanismo della 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.
+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
@@ -4110,26 +4180,23 @@ effettive del file o della sezione che si vuole mappare.
 
 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.
+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}.
+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
@@ -4172,50 +4239,54 @@ consentita la scrittura sul file (cioè per un file mappato con
 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
+direttamente dalla memoria virtuale, occorre essere consapevoli delle
+interazioni che possono esserci con operazioni effettuate con l'interfaccia
+dei file ordinaria illustrata in 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 ordinaria 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} 
+Per questo è sempre sconsigliabile eseguire scritture su un file attraverso
+l'interfaccia ordinaria quando lo si è mappato in memoria, è invece possibile
+usare l'interfaccia ordinaria 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 è:
 
-  \funcdecl{int msync(const void *start, size\_t length, int flags)}
-  
-  Sincronizza i contenuti di una sezione di un file mappato in memoria.
-  
-  \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
-    errore nel qual caso \var{errno} assumerà uno dei valori:
-    \begin{errlist}
+\begin{funcproto}{
+%\fhead{unistd.h}
+\fhead{sys/mman.h}
+\fdecl{int msync(const void *start, size\_t length, int flags)}
+\fdesc{Sincronizza i contenuti di una sezione di un file mappato in memoria.} 
+}
+
+{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{EBUSY}] si è indicato \const{MS\_INVALIDATE} ma
+      nell'intervallo di memoria specificato è presente un \textit{memory lock}.
+    \item[\errcode{EFAULT}] l'intervallo indicato, o parte di esso, non
+      risulta mappato (prima del kernel 2.4.19).
     \item[\errcode{EINVAL}] o \param{start} non è multiplo di
       \const{PAGE\_SIZE}, o si è specificato un valore non valido per
       \param{flags}.
-    \item[\errcode{EFAULT}] l'intervallo specificato non ricade in una zona
-      precedentemente mappata.
-    \end{errlist}
-  }
-\end{functions}
+    \item[\errcode{ENOMEM}] l'intervallo indicato, o parte di esso, non
+      risulta mappato (dal kernel 2.4.19).
+  \end{errlist}
+}
+\end{funcproto}
 
 La funzione esegue la sincronizzazione di quanto scritto nella sezione di
 memoria indicata da \param{start} e \param{offset}, scrivendo le modifiche sul
 file (qualora questo non sia già stato fatto).  Provvede anche ad aggiornare i
 relativi tempi di modifica. In questo modo si è sicuri che dopo l'esecuzione
-di \func{msync} le funzioni dell'interfaccia standard troveranno un contenuto
+di \func{msync} le funzioni dell'interfaccia ordinaria troveranno un contenuto
 del file aggiornato.
 
 
@@ -4246,28 +4317,28 @@ dei valori riportati in tab.~\ref{tab:file_mmap_msync}, di questi però
 infatti la funzione si limita ad inoltrare la richiesta di sincronizzazione al
 meccanismo della memoria virtuale, ritornando subito, mentre con il secondo
 attende che la sincronizzazione sia stata effettivamente eseguita. Il terzo
-flag fa sì che vengano invalidate, per tutte le mappature dello stesso file,
+valore fa sì che vengano invalidate, per tutte le mappature dello stesso file,
 le pagine di cui si è richiesta la sincronizzazione, così che esse possano
 essere immediatamente aggiornate con i nuovi valori.
 
 Una volta che si sono completate le operazioni di I/O si può eliminare la
 mappatura della memoria usando la funzione \funcd{munmap}, il suo prototipo è:
-\begin{functions}  
-  \headdecl{unistd.h}
-  \headdecl{sys/mman.h} 
 
-  \funcdecl{int munmap(void *start, size\_t length)}
-  
-  Rilascia la mappatura sulla sezione di memoria specificata.
+\begin{funcproto}{
+%\fhead{unistd.h}
+\fhead{sys/mman.h}
+\fdecl{int munmap(void *start, size\_t length)}
+\fdesc{Rilascia la mappatura sulla sezione di memoria specificata.} 
+}
 
-  \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
-    errore nel qual caso \var{errno} assumerà uno dei valori:
-    \begin{errlist}
+{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{EINVAL}] l'intervallo specificato non ricade in una zona
       precedentemente mappata.
-    \end{errlist}
-  }
-\end{functions}
+  \end{errlist}
+}
+\end{funcproto}
 
 La funzione cancella la mappatura per l'intervallo specificato con
 \param{start} e \param{length}; ogni successivo accesso a tale regione causerà
@@ -4444,38 +4515,39 @@ partire dal quale la sezione di file indicata verrà rimappata. L'argomento
 valori di \func{mmap} (quelli di tab.~\ref{tab:file_mmap_prot}) ma di tutti i
 flag solo \const{MAP\_NONBLOCK} non viene ignorato.
 
+\itindbeg{prefaulting} 
+
 Insieme alla funzione \func{remap\_file\_pages} nel kernel 2.5.46 con sono
 stati introdotti anche due nuovi flag per \func{mmap}: \const{MAP\_POPULATE} e
 \const{MAP\_NONBLOCK}.  Il primo dei due consente di abilitare il meccanismo
-del \itindex{prefaulting} \textit{prefaulting}. Questo viene di nuovo in aiuto
-per migliorare le prestazioni in certe condizioni di utilizzo del
-\textit{memory mapping}. 
+del \textit{prefaulting}. Questo viene di nuovo in aiuto per migliorare le
+prestazioni in certe condizioni di utilizzo del \textit{memory mapping}.
 
 Il problema si pone tutte le volte che si vuole mappare in memoria un file di
-grosse dimensioni. Il comportamento normale del sistema della
-\index{memoria~virtuale} memoria virtuale è quello per cui la regione mappata
-viene aggiunta alla \itindex{page~table} \textit{page table} del processo, ma
-i dati verranno effettivamente utilizzati (si avrà cioè un
-\itindex{page~fault} \textit{page fault} che li trasferisce dal disco alla
-memoria) soltanto in corrispondenza dell'accesso a ciascuna delle pagine
-interessate dal \textit{memory mapping}. 
+grosse dimensioni. Il comportamento normale del sistema della memoria virtuale
+è quello per cui la regione mappata viene aggiunta alla \textit{page table}
+del processo, ma i dati verranno effettivamente utilizzati (si avrà cioè un
+\textit{page fault} che li trasferisce dal disco alla memoria) soltanto in
+corrispondenza dell'accesso a ciascuna delle pagine interessate dal
+\textit{memory mapping}.
 
 Questo vuol dire che il passaggio dei dati dal disco alla memoria avverrà una
 pagina alla volta con un gran numero di \itindex{page~fault} \textit{page
   fault}, chiaramente se si sa in anticipo che il file verrà utilizzato
-immediatamente, è molto più efficiente eseguire un \itindex{prefaulting}
-\textit{prefaulting} in cui tutte le pagine di memoria interessate alla
-mappatura vengono ``\textsl{popolate}'' in una sola volta, questo
-comportamento viene abilitato quando si usa con \func{mmap} il flag
-\const{MAP\_POPULATE}.
+immediatamente, è molto più efficiente eseguire un \textit{prefaulting} in cui
+tutte le pagine di memoria interessate alla mappatura vengono
+``\textsl{popolate}'' in una sola volta, questo comportamento viene abilitato
+quando si usa con \func{mmap} il flag \const{MAP\_POPULATE}.
 
 Dato che l'uso di \const{MAP\_POPULATE} comporta dell'I/O su disco che può
 rallentare l'esecuzione di \func{mmap} è stato introdotto anche un secondo
-flag, \const{MAP\_NONBLOCK}, che esegue un \itindex{prefaulting}
-\textit{prefaulting} più limitato in cui vengono popolate solo le pagine della
-mappatura che già si trovano nella cache del kernel.\footnote{questo può
-  essere utile per il linker dinamico, in particolare quando viene effettuato
-  il \textit{prelink} delle applicazioni.}
+flag, \const{MAP\_NONBLOCK}, che esegue un \textit{prefaulting} più limitato
+in cui vengono popolate solo le pagine della mappatura che già si trovano
+nella cache del kernel.\footnote{questo può essere utile per il linker
+  dinamico, in particolare quando viene effettuato il \textit{prelink} delle
+  applicazioni.}
+
+\itindend{prefaulting}
 
 Per i vantaggi illustrati all'inizio del paragrafo l'interfaccia del
 \textit{memory mapped I/O} viene usata da una grande varietà di programmi,
@@ -5348,11 +5420,10 @@ all'accesso al disco; il suo prototipo è:
 
 La funzione richiede che venga letto in anticipo il contenuto del file
 \param{fd} a partire dalla posizione \param{offset} e per un ammontare di
-\param{count} byte, in modo da portarlo in cache.  La funzione usa la
-\index{memoria~virtuale} memoria virtuale ed il meccanismo della
-\index{paginazione} paginazione per cui la lettura viene eseguita in blocchi
-corrispondenti alle dimensioni delle pagine di memoria, ed i valori di
-\param{offset} e \param{count} vengono arrotondati di conseguenza.
+\param{count} byte, in modo da portarlo in cache.  La funzione usa la memoria
+virtuale ed il meccanismo della paginazione per cui la lettura viene eseguita
+in blocchi corrispondenti alle dimensioni delle pagine di memoria, ed i valori
+di \param{offset} e \param{count} vengono arrotondati di conseguenza.
 
 La funzione estende quello che è un comportamento normale del kernel che
 quando si legge un file, aspettandosi che l'accesso prosegua, esegue sempre
@@ -5607,7 +5678,8 @@ livello di kernel.
 % http://kernelnewbies.org/Linux_2_6_23
 
 % TODO aggiungere FALLOC_FL_ZERO_RANGE e FALLOC_FL_COLLAPSE_RANGE, inseriti
-% nel kenrel 3.15 (sul secondo vedi http://lwn.net/Articles/589260/)
+% nel kernel 3.15 (sul secondo vedi http://lwn.net/Articles/589260/), vedi
+% anche http://lwn.net/Articles/629965/
 
 % TODO non so dove trattarli, ma dal 2.6.39 ci sono i file handle, vedi
 % http://lwn.net/Articles/432757/