\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.
+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.
+
+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.}
\funcd{aio\_read} ed \funcd{aio\_write}. Esse permettono di richiedere una
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{EBADF}] si è specificato un file descriptor sbagliato.
\item[\errcode{ENOSYS}] la funzione non è implementata.
\item[\errcode{EAGAIN}] la coda delle richieste è momentaneamente piena.
\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
precedente non sia stata ultimata. In generale per ogni operazione si deve
utilizzare una diversa struttura \struct{aiocb}.
+% vedere anche http://davmac.org/davpage/linux/async-io.html e
+% http://www.ibm.com/developerworks/linux/library/l-async/
+
Dato che si opera in modalità asincrona, il successo di \func{aio\_read} o
\func{aio\_write} non implica che le operazioni siano state effettivamente
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}
-Se l'operazione non si è ancora completata viene restituito l'errore di
-\errcode{EINPROGRESS}. La funzione ritorna zero quando l'operazione si è
+\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 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} 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 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,
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}