%% fileadv.tex
%%
-%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2009 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",
\end{prototype}
La funzione è sostanzialmente identica a \func{select}, solo che usa una
-struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timeval_struct}) per
+struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timespec_struct}) per
indicare con maggiore precisione il timeout e non ne aggiorna il valore in
caso di interruzione.\footnote{in realtà la system call di Linux aggiorna il
valore al tempo rimanente, ma la funzione fornita dalle \acr{glibc} modifica
\subsection{Il \textit{Signal driven I/O}}
\label{sec:file_asyncronous_operation}
+\itindbeg{signal~driven~I/O}
+
Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso
l'uso del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e
dei comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è
(vedi sez.~\ref{sec:sig_real_time}) impostando esplicitamente con il comando
\const{F\_SETSIG} di \func{fcntl} un segnale real-time da inviare in caso di
I/O asincrono (il segnale predefinito è \const{SIGIO}). In questo caso il
-gestore, tutte le volte che riceverà \const{SI\_SIGIO} come valore del
-campo \var{si\_code}\footnote{il valore resta \const{SI\_SIGIO} qualunque sia
- il segnale che si è associato all'I/O asincrono, ed indica appunto che il
- segnale è stato generato a causa di attività nell'I/O asincrono.} di
-\struct{siginfo\_t}, troverà nel campo \var{si\_fd} il valore del file
-descriptor che ha generato il segnale.
+gestore, tutte le volte che riceverà \const{SI\_SIGIO} come valore del campo
+\var{si\_code}\footnote{il valore resta \const{SI\_SIGIO} qualunque sia il
+ segnale che si è associato all'I/O, ed indica appunto che il segnale è stato
+ generato a causa di attività di I/O.} di \struct{siginfo\_t}, troverà nel
+campo \var{si\_fd} il valore del file descriptor che ha generato il segnale.
Un secondo vantaggio dell'uso dei segnali real-time è che essendo questi
ultimi dotati di una coda di consegna ogni segnale sarà associato ad uno solo
anche questa funzionalità. In questo modo si può identificare immediatamente
un file su cui l'accesso è diventato possibile evitando completamente l'uso di
funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
-la coda.
+la coda.
Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non potendo
più assicurare il comportamento corretto per un segnale real-time, invierà al
% TODO fare esempio che usa O_ASYNC
+\itindend{signal~driven~I/O}
+
+
\subsection{I meccanismi di notifica asincrona.}
\label{sec:file_asyncronous_lease}
\textit{lease breaker}, cerca di eseguire una \func{open} o una
\func{truncate} sul file del quale l'\textit{holder} detiene il
\textit{lease}.
-
La notifica avviene in maniera analoga a come illustrato in precedenza per
l'uso di \const{O\_ASYNC}: di default viene inviato al \textit{lease holder}
il segnale \const{SIGIO}, ma questo segnale può essere modificato usando il
Inoltre trattandosi di un file descriptor a tutti gli effetti, esso potrà
essere utilizzato come argomento per le funzioni \func{select} e \func{poll} e
-con l'interfaccia di \textit{epoll}; siccome gli eventi vengono notificati
-come dati disponibili in lettura, dette funzioni ritorneranno tutte le volte
-che si avrà un evento di notifica. Così, invece di dover utilizzare i
+con l'interfaccia di \textit{epoll};\footnote{ed a partire dal kernel 2.6.25 è
+ stato introdotto anche il supporto per il \itindex{signal~driven~I/O}
+ \texttt{signal-driven I/O} trattato in
+ sez.~\ref{sec:file_asyncronous_operation}.} siccome gli eventi vengono
+notificati come dati disponibili in lettura, dette funzioni ritorneranno tutte
+le volte che si avrà un evento di notifica. Così, invece di dover utilizzare i
segnali,\footnote{considerati una pessima scelta dal punto di vista
dell'interfaccia utente.} si potrà gestire l'osservazione degli eventi con
una qualunque delle modalità di \textit{I/O multiplexing} illustrate in
\index{file!inotify|)}
+% TODO trattare fanotify, vedi http://lwn.net/Articles/339399/ e
+% http://lwn.net/Articles/343346/
+
\subsection{L'interfaccia POSIX per l'I/O asincrono}
\label{sec:file_asyncronous_io}
In generale questa interfaccia è completamente astratta e può essere
implementata sia direttamente nel kernel, che in user space attraverso l'uso
-di 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.
+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
fig.~\ref{fig:sig_sigval}) come valore del campo \var{si\_value} di
\struct{siginfo\_t}.
\item[\const{SIGEV\_THREAD}] La notifica viene effettuata creando un nuovo
- thread che esegue la funzione specificata da \var{sigev\_notify\_function}
- con argomento \var{sigev\_value}, e con gli attributi specificati da
- \var{sigev\_notify\_attribute}.
+ \itindex{thread} \textit{thread} che esegue la funzione specificata da
+ \var{sigev\_notify\_function} con argomento \var{sigev\_value}, e con gli
+ attributi specificati da \var{sigev\_notify\_attribute}.
\end{basedescript}
Le due funzioni base dell'interfaccia per l'I/O asincrono sono
\label{tab:file_mmap_prot}
\end{table}
-Il valore dell'argomento \param{prot} indica la protezione\footnote{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
- che si chiama una \textit{segment violation}, e la relativa emissione del
- segnale \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere
+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
+ \const{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.
un \const{SIGSEGV}.\\
\const{MAP\_LOCKED} & Se impostato impedisce lo swapping delle pagine
mappate.\\
- \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} stack. Indica
- che la mappatura deve essere effettuata con gli
- indirizzi crescenti verso il basso.\\
+ \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\\
\itindend{memory~mapping}
+% TODO documentare \func{madvise}
+
\subsection{I/O vettorizzato: \func{readv} e \func{writev}}
\label{sec:file_multiple_io}
% TODO verificare cosa succederà a preadv e pwritev o alla nuova niovec
% vedi http://lwn.net/Articles/164887/
+% inserite nel kernel 2.6.30, vedi http://lwn.net/Articles/326818/
\subsection{L'I/O diretto fra file descriptor: \func{sendfile} e \func{splice}}
portato, per i kernel della serie 2.6,\footnote{per alcune motivazioni di
questa scelta si può fare riferimento a quanto illustrato da Linus Torvalds
in \href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}
- {\texttt{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}.}
+ {\textsf{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}.}
alla decisione di consentire l'uso della funzione soltanto quando il file da
cui si legge supporta le operazioni di \textit{memory mapping} (vale a dire
non è un socket) e quello su cui si scrive è un socket; in tutti gli altri
sarebbe altro che la lettura degli stessi su un buffer seguita dalla
relativa scrittura, cosa che in questo caso si dovrebbe eseguire con due
chiamate a \func{splice}.} In realtà le due system call sono profondamente
-diverse nel loro meccanismo di funzionamento; \func{sendfile} infatti, come
-accennato, non necessita affatto di avere a disposizione un buffer interno,
-perché esegue un trasferimento diretto di dati; questo la rende in generale
-molto più efficiente, ma anche limitata nelle sue applicazioni, dato che
-questo tipo di trasferimento è possibile solo in casi specifici.\footnote{e
- nel caso di Linux questi sono anche solo quelli in cui essa può essere
- effettivamente utilizzata.}
+diverse nel loro meccanismo di funzionamento;\footnote{questo fino al kernel
+ 2.6.23, dove \func{sendfile} è stata reimplementata in termini di
+ \func{splice}, pur mantenendo disponibile la stessa interfaccia verso l'user
+ space.} \func{sendfile} infatti, come accennato, non necessita di avere a
+disposizione un buffer interno, perché esegue un trasferimento diretto di
+dati; questo la rende in generale più efficiente, ma anche limitata nelle sue
+applicazioni, dato che questo tipo di trasferimento è possibile solo in casi
+specifici.\footnote{e nel caso di Linux questi sono anche solo quelli in cui
+ essa può essere effettivamente utilizzata.}
Il concetto che sta dietro a \func{splice} invece è diverso,\footnote{in
realtà la proposta originale di Larry Mc Voy non differisce poi tanto negli
stata la reinterpretazione che ne è stata fatta nell'implementazione su
Linux realizzata da Jens Anxboe, concetti che sono esposti sinteticamente
dallo stesso Linus Torvalds in \href{http://kerneltrap.org/node/6505}
- {\texttt{http://kerneltrap.org/node/6505}}.} si tratta semplicemente di una
+ {\textsf{http://kerneltrap.org/node/6505}}.} si tratta semplicemente di una
funzione che consente di fare in maniera del tutto generica delle operazioni
di trasferimento di dati fra un file e un buffer gestito interamente in kernel
space. In questo caso il cuore della funzione (e delle affini \func{vmsplice}
realizza le \textit{pipe} come un insieme di puntatori\footnote{per essere
precisi si tratta di un semplice buffer circolare, un buon articolo sul tema
si trova su \href{http://lwn.net/Articles/118750/}
- {\texttt{http://lwn.net/Articles/118750/}}.} alle pagine di memoria interna
+ {\textsf{http://lwn.net/Articles/118750/}}.} alle pagine di memoria interna
che contengono i dati, per questo una volta che i dati sono presenti nella
memoria del kernel tutto quello che viene fatto è creare i suddetti puntatori
ed aumentare il numero di referenze; questo significa che anche con \func{tee}
non viene mai copiato nessun byte, vengono semplicemente copiati i puntatori.
+% TODO?? dal 2.6.25 splice ha ottenuto il supporto per la ricezione su rete
\subsection{Gestione avanzata dell'accesso ai dati dei file}
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} bytes, in modo da portarlo in cache. La funzione usa la
+\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
La funzione dichiara al kernel le modalità con cui intende accedere alla
regione del file indicato da \param{fd} che inizia alla posizione
\param{offset} e si estende per \param{len} byte. Se per \param{len} si usa un
-valora nullo la regione coperta sarà da \param{offset} alla fine del
+valore nullo la regione coperta sarà da \param{offset} alla fine del
file.\footnote{questo è vero solo per le versioni più recenti, fino al kernel
2.6.6 il valore nullo veniva interpretato letteralmente.} Le modalità sono
indicate dall'argomento \param{advice} che è una maschera binaria dei valori
illustrati in tab.~\ref{tab:posix_fadvise_flag}. Si tenga presente comunque
che la funzione dà soltanto un avvertimento, non esiste nessun vincolo per il
-kernel, che utilzza semplicemente l'informazione.
+kernel, che utilizza semplicemente l'informazione.
\begin{table}[htb]
\centering
comportamento sarà identico a quello che si
avrebbe senza nessun avviso.\\
\const{POSIX\_FADV\_SEQUENTIAL}& L'applicazione si aspetta di accedere di
- accedere ai dati spercificati in maniera
+ accedere ai dati specificati in maniera
sequenziale, a partire dalle posizioni più
basse.\\
\const{POSIX\_FADV\_RANDOM} & I dati saranno letti in maniera
- completamete causale.\\
+ completamente causale.\\
\const{POSIX\_FADV\_NOREUSE} & I dati saranno acceduti una sola volta.\\
\const{POSIX\_FADV\_WILLNEED}& I dati saranno acceduti a breve.\\
\const{POSIX\_FADV\_DONTNEED}& I dati non saranno acceduti a breve.\\
Anche \func{posix\_fadvise} si appoggia al sistema della memoria virtuale ed
al meccanismo standard del \textit{readahead} utilizzato dal kernel; in
particolare con \const{POSIX\_FADV\_SEQUENTIAL} si raddoppia la dimensione
-dell'ammontare di dati letti preventivamente rispetto al default, apettandosi
+dell'ammontare di dati letti preventivamente rispetto al default, aspettandosi
appunto una lettura sequenziale che li utilizzerà, mentre con
\const{POSIX\_FADV\_RANDOM} si disabilita del tutto il suddetto meccanismo,
dato che con un accesso del tutto casuale è inutile mettersi a leggere i dati
che inizia dalla posizione \param{offset} e si estende per \param{len} byte;
se questa si estende oltre la fine del file le dimensioni di quest'ultimo
saranno incrementate di conseguenza. Dopo aver eseguito con successo la
-funzione è garantito che una scrittura nella regione inidicata non fallirà per
+funzione è garantito che una scrittura nella regione indicata non fallirà per
mancanza di spazio disco.
+% TODO controllare la trattazione della nuova funzionalità di preallocazione
-
% TODO documentare \func{posix\_fadvise}
% vedi http://insights.oetiker.ch/linux/fadvise.html
% questo tread? http://www.ussg.iu.edu/hypermail/linux/kernel/0703.1/0032.html
% TODO documentare \func{fallocate}, introdotta con il 2.6.23
% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
+% http://kernelnewbies.org/Linux_2_6_23
+% \func{fallocate} con il 2.6.25 supporta pure XFS
%\subsection{L'utilizzo delle porte di I/O}
% LocalWords: NUL sizeof casting printevent nread limits sysconf SC wrapper Di
% LocalWords: splice result argument DMA controller zerocopy Linus Larry Voy
% LocalWords: Jens Anxboe vmsplice seek ESPIPE GIFT TCP CORK MSG splicecp nr
-% LocalWords: nwrite segs patch readahead
+% LocalWords: nwrite segs patch readahead posix fadvise TC advice FADV NORMAL
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "gapil"
%%% End:
+% LocalWords: SEQUENTIAL NOREUSE WILLNEED DONTNEED streaming fallocate EFBIG