Finito asyncronous I/O, iniziato mmap.
[gapil.git] / fileadv.tex
index 88f6307d5383a74301d8e738a74138b49f6833ae..38da0ecff3796640fb330035813107e0edb17ce1 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
@@ -3493,50 +3494,50 @@ 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}. Il concetto base dell'\textsl{I/O asincrono} è che le funzioni
-di I/O non attendono il completamento delle operazioni prima di 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, che prevede un insieme di funzioni dedicate per la lettura e
-la scrittura dei file, completamente separate rispetto a quelle usate
-normalmente.
+  asincrono} o ``AIO''. Il concetto base dell'\textsl{I/O asincrono} è che le
+funzioni di I/O non attendono il completamento delle operazioni prima di
+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 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
-esiste una implementazione di questa interfaccia fornita delle \acr{glibc},
-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 direttamente nel kernel un nuovo layer per
-l'I/O asincrono.
-
-Lo standard prevede che tutte le operazioni di I/O asincrono siano controllate
-attraverso l'uso di una apposita struttura \struct{aiocb} (il cui nome sta per
-\textit{asyncronous I/O control block}), che viene passata come argomento a
-tutte le funzioni dell'interfaccia. La sua definizione, come effettuata in
-\headfile{aio.h}, è riportata in fig.~\ref{fig:file_aiocb}. Nello steso file è
-definita la macro \macro{\_POSIX\_ASYNCHRONOUS\_IO}, che dichiara la
-disponibilità dell'interfaccia per l'I/O asincrono.
+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}. 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
+nome sta per \textit{asyncronous I/O control block}), che viene passata come
+argomento a tutte le funzioni dell'interfaccia. La sua definizione, come
+effettuata in \headfile{aio.h}, è riportata in
+fig.~\ref{fig:file_aiocb}. Nello steso file è definita la macro
+\macro{\_POSIX\_ASYNCHRONOUS\_IO}, che dichiara la disponibilità
+dell'interfaccia per l'I/O asincrono.
 
 \begin{figure}[!htb]
   \footnotesize \centering
-  \begin{minipage}[c]{\textwidth}
+  \begin{minipage}[c]{0.90\textwidth}
     \includestruct{listati/aiocb.h}
-  \end{minipage} 
+  \end{minipage}
   \normalsize 
   \caption{La struttura \structd{aiocb}, usata per il controllo dell'I/O
     asincrono.}
@@ -3557,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
@@ -3576,45 +3577,44 @@ 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{functions}
-  \headdecl{aio.h}
 
-  \funcdecl{int aio\_read(struct aiocb *aiocbp)}
-  Richiede una lettura asincrona secondo quanto specificato con \param{aiocbp}.
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_read(struct aiocb *aiocbp)}
+\fdesc{Richiede una lettura asincrona.} 
+\fdecl{int aio\_write(struct aiocb *aiocbp)}
+\fdesc{Richiede una scrittura asincrona.} 
+}
 
-  \funcdecl{int aio\_write(struct aiocb *aiocbp)}
-  Richiede una scrittura asincrona secondo quanto specificato con
-  \param{aiocbp}.
-  
-  \bodydesc{Le funzioni restituiscono 0 in caso di successo, e -1 in caso di
-    errore, nel qual caso \var{errno} assumerà uno dei valori:
+{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{functions}
+\end{funcproto}
+
 
 Entrambe le funzioni ritornano immediatamente dopo aver messo in coda la
 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
@@ -3626,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.} 
+}
+
+{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 restituito l'errore di
-\errcode{EINPROGRESS}. La funzione ritorna zero quando l'operazione si è
+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 ritorna lo stato di uscita dell'operazione eseguita (il valore
+  che avrebbero restituito le equivalenti funzioni eseguite in maniera
+  sincrona).}
+\end{funcproto}
 
-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 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.} 
+}
 
-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 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}
 
-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
+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{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,
@@ -3752,64 +3774,79 @@ 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.
@@ -3818,7 +3855,7 @@ che può prendere i valori:
 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
@@ -3828,6 +3865,12 @@ 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}
@@ -3847,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]
@@ -3893,56 +3936,60 @@ 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 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} ($-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).
+    \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{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 valore diverso da \val{NULL},
+in cui di 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
@@ -3991,19 +4038,43 @@ 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 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\_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\_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}   & da trattare (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
@@ -4014,64 +4085,35 @@ tab.~\ref{tab:file_mmap_flag}.
                              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\\
+                             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.\\
-%     \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
+\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}.}
 
-\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.}
+% 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