X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileadv.tex;h=38bd320f168b551fed88b316b62baf50e2f81272;hp=8a458809c5731600d4013eecb7ac5f9bf63de291;hb=50b469ec4e7bba4d52eaaa51edd77b18967079c2;hpb=5d10cf6f53b2ae74e34cbfa335df074f2093e142 diff --git a/fileadv.tex b/fileadv.tex index 8a45880..38bd320 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1,6 +1,6 @@ %% fileadv.tex %% -%% Copyright (C) 2000-2009 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2010 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", @@ -2076,7 +2076,7 @@ kernel \textit{lease breaker} rimaste bloccate proseguono automaticamente. -\index{file!dnotify|(} +\itindbeg{dnotify} Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da parte di più processi, l'uso dei \textit{file lease} non consente comunque di @@ -2154,7 +2154,7 @@ specificate in chiamate successive vengono aggiunte a quelle gi nelle precedenti. Se si vuole rimuovere la notifica si deve invece specificare un valore nullo. -\index{file!inotify|(} +\itindbeg{inotify} Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve usare un file descriptor per ciascuna directory che si vuole tenere sotto @@ -2174,7 +2174,7 @@ sez.~\ref{sec:sig_adv_control}. Per tutta questa serie di motivi in generale quella di \textit{dnotify} viene considerata una interfaccia di usabilità problematica. -\index{file!dnotify|)} +\itindend{dnotify} Per risolvere i problemi appena illustrati è stata introdotta una nuova interfaccia per l'osservazione delle modifiche a file o directory, chiamata @@ -2656,7 +2656,7 @@ verificano pi dei campi \var{wd}, \var{mask}, \var{cookie}, e \var{name}) questi vengono raggruppati in un solo evento. -\index{file!inotify|)} +\itindend{inotify} % TODO trattare fanotify, vedi http://lwn.net/Articles/339399/ e % http://lwn.net/Articles/343346/ @@ -2736,17 +2736,6 @@ 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. -\begin{figure}[!htb] - \footnotesize \centering - \begin{minipage}[c]{15cm} - \includestruct{listati/sigevent.h} - \end{minipage} - \normalsize - \caption{La struttura \structd{sigevent}, usata per specificare le modalità - di notifica degli eventi relativi alle operazioni di I/O asincrono.} - \label{fig:file_sigevent} -\end{figure} - Infine il campo \var{aio\_sigevent} è una struttura di tipo \struct{sigevent} che serve a specificare il modo in cui si vuole che venga effettuata la notifica del completamento delle operazioni richieste. La struttura è @@ -3761,8 +3750,6 @@ tab.~\ref{tab:madvise_advice_values}. \label{tab:madvise_advice_values} \end{table} -%TODO aggiungere MADV_MERGEABLE, vedi http://kernelnewbies.org/Linux_2_6_32 - \footnotetext{se usato su altri tipi di filesystem causa un errore di \errcode{ENOSYS}.} @@ -3880,22 +3867,60 @@ ma si perder Si tenga presente infine che queste funzioni operano sui file con l'interfaccia dei file descriptor, e non è consigliabile mescolarle con -l'interfaccia classica dei \textit{file stream}; a causa delle bufferizzazioni -interne di quest'ultima infatti si potrebbero avere risultati indefiniti e non -corrispondenti a quanto aspettato. +l'interfaccia classica dei \textit{file stream} di +cap.~\ref{cha:files_std_interface}; a causa delle bufferizzazioni interne di +quest'ultima infatti si potrebbero avere risultati indefiniti e non +corrispondenti a quanto aspettato. Come per le normali operazioni di lettura e scrittura, anche per l'\textsl{I/O vettorizzato} si pone il problema di poter effettuare le operazioni in -maniera atomica a partire da un certa posizione sul file; per questo motivo a +maniera atomica a partire da un certa posizione sul file. Per questo motivo a partire dal kernel 2.6.30 sono state introdotte anche per l'\textsl{I/O vettorizzato} le analoghe delle funzioni \func{pread} e \func{pwrite} (vedi -sez.~\ref{sec:file_read} e \ref{sec:file_write}) che consentono di effettuare -letture e scritture vettorizzate a partire da una certa posizione. Le due -funzioni sono \funcd{preadv} e \func{pwritev} ed i rispettivi prototipi sono: +sez.~\ref{sec:file_read} e \ref{sec:file_write}); le due funzioni sono +\funcd{preadv} e \func{pwritev} ed i rispettivi prototipi sono:\footnote{le + due funzioni sono analoghe alle omonime presenti in BSD; le \textit{system + call} usate da Linux (introdotte a partire dalla versione 2.6.30) + utilizzano degli argomenti diversi per problemi collegati al formato a 64 + bit dell'argomento \param{offset}, che varia a seconda delle architetture, + ma queste differenze vengono gestite dalle funzioni di librerie di libreria + che mantengono l'interfaccia delle analoghe tratte da BSD.} +\begin{functions} + \headdecl{sys/uio.h} + + \funcdecl{int preadv(int fd, const struct iovec *vector, int count, off\_t + offset)} + \funcdecl{int pwritev(int fd, const struct iovec *vector, int count, off\_t + offset)} + + Eseguono una lettura o una scrittura vettorizzata a partire da una data + posizione sul file. + + \bodydesc{Le funzioni hanno gli stessi valori di ritorno delle + corrispondenti \func{readv} e \func{writev}; anche gli eventuali errori + sono gli stessi già visti in precedenza, ma ad essi si possono aggiungere + per \var{errno} anche i valori: + \begin{errlist} + \item[\errcode{EOVERFLOW}] \param{offset} ha un valore che non può essere + usato come \ctyp{off\_t}. + \item[\errcode{ESPIPE}] \param{fd} è associato ad un socket o una pipe. + \end{errlist} +} +\end{functions} + +Le due funzioni eseguono rispettivamente una lettura o una scrittura +vettorizzata a partire dalla posizione \param{offset} sul file indicato +da \param{fd}, la posizione corrente sul file, come vista da eventuali altri +processi che vi facciano riferimento, non viene alterata. A parte la presenza +dell'ulteriore argomento il comportamento delle funzioni è identico alle +precedenti \func{readv} e \func{writev}. -% 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/ +Con l'uso di queste funzioni si possono evitare eventuali +\itindex{race~condition} \textit{race condition} quando si deve eseguire la +una operazione di lettura e scrittura vettorizzata a partire da una certa +posizione su un file, mentre al contempo si possono avere in concorrenza +processi che utilizzano lo stesso file descriptor (si ricordi quanto visto in +sez.~\ref{sec:file_adv_func}) con delle chiamate a \func{lseek}. @@ -3916,15 +3941,15 @@ efficiente mantenere tutto in kernel space. Tratteremo in questa sezione alcune funzioni specialistiche che permettono di ottimizzare le prestazioni in questo tipo di situazioni. -La prima funzione che si pone l'obiettivo di ottimizzare il trasferimento dei -dati fra due file descriptor è \funcd{sendfile};\footnote{la funzione è stata +La prima funzione che è stata ideata per ottimizzare il trasferimento dei dati +fra due file descriptor è \func{sendfile};\footnote{la funzione è stata introdotta con i kernel della serie 2.2, e disponibile dalle \acr{glibc} 2.1.} la funzione è presente in diverse versioni di Unix,\footnote{la si ritrova ad esempio in FreeBSD, HPUX ed altri Unix.} ma non è presente né in POSIX.1-2001 né in altri standard,\footnote{pertanto si eviti di utilizzarla se si devono scrivere programmi portabili.} per cui per essa vengono -utilizzati prototipi e semantiche differenti; nel caso di Linux il suo -prototipo è: +utilizzati prototipi e semantiche differenti; nel caso di Linux il prototipo +di \funcd{sendfile} è: \begin{functions} \headdecl{sys/sendfile.h} @@ -3953,7 +3978,7 @@ prototipo La funzione copia direttamente \param{count} byte dal file descriptor \param{in\_fd} al file descriptor \param{out\_fd}; in caso di successo funzione ritorna il numero di byte effettivamente copiati da \param{in\_fd} a -\param{out\_fd} o $-1$ in caso di errore, come le ordinarie \func{read} e +\param{out\_fd} o $-1$ in caso di errore; come le ordinarie \func{read} e \func{write} questo valore può essere inferiore a quanto richiesto con \param{count}. @@ -4001,19 +4026,16 @@ non casi l'uso di \func{sendfile} darà luogo ad un errore di \errcode{EINVAL}. Nonostante ci possano essere casi in cui \func{sendfile} non migliora le -prestazioni, le motivazioni addotte non convincono del tutto e resta il dubbio -se la scelta di disabilitarla sempre per il trasferimento di dati fra file di -dati sia davvero corretta. Se ci sono peggioramenti di prestazioni infatti si -può sempre fare ricorso all'uso successivo di, ma lasciare a disposizione la -funzione consentirebbe se non altro, anche in assenza di guadagni di -prestazioni, di semplificare la gestione della copia dei dati fra file, -evitando di dover gestire l'allocazione di un buffer temporaneo per il loro -trasferimento; inoltre si avrebbe comunque il vantaggio di evitare inutili -trasferimenti di dati da kernel space a user space e viceversa. - -Questo dubbio si può comunque ritenere superato con l'introduzione, avvenuto a -partire dal kernel 2.6.17, della nuova system call \func{splice}. Lo scopo di -questa funzione è quello di fornire un meccanismo generico per il +prestazioni, resta il dubbio se la scelta di disabilitarla sempre per il +trasferimento fra file di dati sia davvero corretta. Se ci sono peggioramenti +di prestazioni infatti si può sempre fare ricorso al metodo ordinario, ma +lasciare a disposizione la funzione consentirebbe se non altro di semplificare +la gestione della copia dei dati fra file, evitando di dover gestire +l'allocazione di un buffer temporaneo per il loro trasferimento. + +Questo dubbio si può comunque ritenere superato con l'introduzione, avvenuta a +partire dal kernel 2.6.17, della nuova \textit{system call} \func{splice}. Lo +scopo di questa funzione è quello di fornire un meccanismo generico per il trasferimento di dati da o verso un file utilizzando un buffer gestito internamente dal kernel. Descritta in questi termini \func{splice} sembra semplicemente un ``\textsl{dimezzamento}'' di \func{sendfile}.\footnote{nel @@ -4175,16 +4197,17 @@ descrizioni complete di tutti i valori possibili anche quando, come per \label{tab:splice_flag} \end{table} -\footnotetext{per una maggiore efficienza \func{splice} usa quando possibile i - meccanismi della memoria virtuale per eseguire i trasferimenti di dati (in - maniera analoga a \func{mmap}), qualora le pagine non possano essere - spostate dalla pipe o il buffer non corrisponda a pagine intere esse saranno - comunque copiate.} +\footnotetext[120]{per una maggiore efficienza \func{splice} usa quando + possibile i meccanismi della memoria virtuale per eseguire i trasferimenti + di dati (in maniera analoga a \func{mmap}), qualora le pagine non possano + essere spostate dalla pipe o il buffer non corrisponda a pagine intere esse + saranno comunque copiate.} -\footnotetext{questa opzione consente di utilizzare delle opzioni di gestione - dei socket che permettono di ottimizzare le trasmissioni via rete, si veda - la descrizione di \const{TCP\_CORK} in sez.~\ref{sec:sock_tcp_udp_options} e - quella di \const{MSG\_MORE} in sez.~\ref{sec:net_sendmsg}.} +\footnotetext[121]{questa opzione consente di utilizzare delle opzioni di + gestione dei socket che permettono di ottimizzare le trasmissioni via rete, + si veda la descrizione di \const{TCP\_CORK} in + sez.~\ref{sec:sock_tcp_udp_options} e quella di \const{MSG\_MORE} in + sez.~\ref{sec:net_sendmsg}.} \footnotetext{questo significa che la cache delle pagine e i dati su disco potranno differire, e che l'applicazione non potrà modificare quest'area di @@ -4281,16 +4304,17 @@ anche se un valore nullo avrebbe dato gli stessi risultati, l'uso di questi flag, che si ricordi servono solo a dare suggerimenti al kernel, permette in genere di migliorare le prestazioni. -Come accennato con l'introduzione di \func{splice} sono state realizzate altre -due system call, \func{vmsplice} e \func{tee}, che utilizzano la stessa -infrastruttura e si basano sullo stesso concetto di manipolazione e +Come accennato con l'introduzione di \func{splice} sono state realizzate anche +altre due \textit{system call}, \func{vmsplice} e \func{tee}, che utilizzano +la stessa infrastruttura e si basano sullo stesso concetto di manipolazione e trasferimento di dati attraverso un buffer in kernel space; benché queste non attengono strettamente ad operazioni di trasferimento dati fra file -descriptor, le tratteremo qui. +descriptor, le tratteremo qui, essendo strettamente correlate fra loro. La prima funzione, \funcd{vmsplice}, è la più simile a \func{splice} e come -indica il suo nome consente di trasferire i dati dalla memoria di un processo -verso una \textit{pipe}, il suo prototipo è: +indica il suo nome consente di trasferire i dati dalla memoria virtuale di un +processo (ad esempio per un file mappato in memoria) verso una \textit{pipe}; +il suo prototipo è: \begin{functions} \headdecl{fcntl.h} \headdecl{sys/uio.h} @@ -4314,22 +4338,27 @@ verso una \textit{pipe}, il suo prototipo } \end{functions} -La \textit{pipe} dovrà essere specificata tramite il file descriptor -corrispondente al suo capo aperto in scrittura (di nuovo si faccia riferimento -a sez.~\ref{sec:ipc_unix}), mentre per indicare quali zone di memoria devono -essere trasferita si deve utilizzare un vettore di strutture \struct{iovec} -(vedi fig.~\ref{fig:file_iovec}), con le stesse con cui le si usano per l'I/O -vettorizzato; le dimensioni del suddetto vettore devono essere passate -nell'argomento \param{nr\_segs} che indica il numero di segmenti di memoria da -trasferire. Sia per il vettore che per il valore massimo di \param{nr\_segs} -valgono le stesse limitazioni illustrate in sez.~\ref{sec:file_multiple_io}. +La \textit{pipe} indicata da \param{fd} dovrà essere specificata tramite il +file descriptor corrispondente al suo capo aperto in scrittura (di nuovo si +faccia riferimento a sez.~\ref{sec:ipc_unix}), mentre per indicare quali +segmenti della memoria del processo devono essere trasferiti verso di essa si +dovrà utilizzare un vettore di strutture \struct{iovec} (vedi +fig.~\ref{fig:file_iovec}), esattamente con gli stessi criteri con cui le si +usano per l'I/O vettorizzato, indicando gli indirizzi e le dimensioni di +ciascun segmento di memoria su cui si vuole operare; le dimensioni del +suddetto vettore devono essere passate nell'argomento \param{nr\_segs} che +indica il numero di segmenti di memoria da trasferire. Sia per il vettore che +per il valore massimo di \param{nr\_segs} valgono le stesse limitazioni +illustrate in sez.~\ref{sec:file_multiple_io}. In caso di successo la funzione ritorna il numero di byte trasferiti sulla -pipe, in generale (se i dati una volta creati non devono essere riutilizzati) -è opportuno utilizzare il flag \const{SPLICE\_F\_GIFT}; questo fa si che il -kernel possa rimuovere le relative pagine dallo spazio degli indirizzi del -processo, e scaricarle nella cache, così che queste possono essere utilizzate -immediatamente senza necessità di eseguire una copia dei dati che contengono. +\textit{pipe}. In generale, se i dati una volta creati non devono essere +riutilizzati (se cioè l'applicazione che chiama \func{vmsplice} non +modificherà più la memoria trasferita), è opportuno utilizzare +per \param{flag} il valore \const{SPLICE\_F\_GIFT}; questo fa sì che il kernel +possa rimuovere le relative pagine dalla cache della memoria virtuale, così +che queste possono essere utilizzate immediatamente senza necessità di +eseguire una copia dei dati che contengono. La seconda funzione aggiunta insieme a \func{splice} è \func{tee}, che deve il suo nome all'omonimo comando in user space, perché in analogia con questo @@ -4364,7 +4393,12 @@ sorgente e \param{fd\_out} il capo in scrittura della \textit{pipe} destinazione; a differenza di quanto avviene con \func{read} i dati letti con \func{tee} da \func{fd\_in} non vengono \textsl{consumati} e restano disponibili sulla \textit{pipe} per una successiva lettura (di nuovo per il -comportamento delle \textit{pipe} si veda sez.~\ref{sec:ipc_unix}). +comportamento delle \textit{pipe} si veda sez.~\ref{sec:ipc_unix}). Al +momento\footnote{quello della stesura di questo paragrafo, avvenuta il Gennaio + 2010, in futuro potrebbe essere implementato anche \const{SPLICE\_F\_MORE}.} +il solo valore utilizzabile per \param{flag}, fra quelli elencati in +tab.~\ref{tab:splice_flag}, è \const{SPLICE\_F\_NONBLOCK} che rende la +funzione non bloccante. La funzione restituisce il numero di byte copiati da una \textit{pipe} all'altra (o $-1$ in caso di errore), un valore nullo indica che non ci sono @@ -4482,35 +4516,37 @@ La funzione richiede che venga letto in anticipo il contenuto del file \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} arrotondati di conseguenza. +\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 una lettura preventiva di una certa quantità di dati; questo meccanismo di lettura anticipata viene chiamato \textit{read-ahead}, da cui deriva il nome -della funzione. La funzione, per ottimizzare gli accessi a disco, effettua la -lettura in cache della sezione richiesta e si blocca fintanto che questa non -viene completata. La posizione corrente sul file non viene modificata ed -indipendentemente da quanto indicato con \param{count} la lettura dei dati si -interrompe una volta raggiunta la fine del file. +della funzione. La funzione \func{readahead}, per ottimizzare gli accessi a +disco, effettua la lettura in cache della sezione richiesta e si blocca +fintanto che questa non viene completata. La posizione corrente sul file non +viene modificata ed indipendentemente da quanto indicato con \param{count} la +lettura dei dati si interrompe una volta raggiunta la fine del file. Si può utilizzare questa funzione per velocizzare le operazioni di lettura -all'interno del programma tutte le volte che si conosce in anticipo quanti -dati saranno necessari in seguito. Si potrà così concentrare in un unico -momento (ad esempio in fase di inizializzazione) la lettura, così da ottenere -una migliore risposta nelle operazioni successive. +all'interno di un programma tutte le volte che si conosce in anticipo quanti +dati saranno necessari nelle elaborazioni successive. Si potrà così +concentrare in un unico momento (ad esempio in fase di inizializzazione) la +lettura dei dati da disco, così da ottenere una migliore velocità di risposta +nelle operazioni successive. \itindend{read-ahead} Il concetto di \func{readahead} viene generalizzato nello standard -POSIX.1-2001 dalla funzione \funcd{posix\_fadvise},\footnote{anche se +POSIX.1-2001 dalla funzione \func{posix\_fadvise},\footnote{anche se l'argomento \param{len} è stato modificato da \ctyp{size\_t} a \ctyp{off\_t} nella revisione POSIX.1-2003 TC5.} che consente di ``\textsl{avvisare}'' il kernel sulle modalità con cui si intende accedere nel futuro ad una certa porzione di un file,\footnote{la funzione però è stata introdotta su Linux solo a partire dal kernel 2.5.60.} così che esso possa provvedere le -opportune ottimizzazioni; il suo prototipo, che può è disponibile solo se si -definisce la macro \macro{\_XOPEN\_SOURCE} ad almeno 600, è: +opportune ottimizzazioni; il prototipo di \funcd{posix\_fadvise}, che è +disponibile soltanto se è stata definita la macro \macro{\_XOPEN\_SOURCE} ad +valore di almeno 600, è: \begin{functions} \headdecl{fcntl.h} @@ -4578,18 +4614,18 @@ che utilizza semplicemente l'informazione. Come \func{madvise} anche \func{posix\_fadvise} si appoggia al sistema della memoria virtuale ed al meccanismo standard del \textit{read-ahead} utilizzato -dal kernel; in particolare con \const{POSIX\_FADV\_SEQUENTIAL} si raddoppia la -dimensione 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 -immediatamente successivi gli attuali; infine l'uso di -\const{POSIX\_FADV\_NORMAL} consente di riportarsi al comportamento di -default. +dal kernel; in particolare utilizzando il valore +\const{POSIX\_FADV\_SEQUENTIAL} si raddoppia la dimensione 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 immediatamente successivi +gli attuali; infine l'uso di \const{POSIX\_FADV\_NORMAL} consente di +riportarsi al comportamento di default. Le due modalità \const{POSIX\_FADV\_NOREUSE} e \const{POSIX\_FADV\_WILLNEED} fino al kernel 2.6.18 erano equivalenti, a partire da questo kernel la prima -viene non ha più alcune effetto, mentre la seconda dà inizio ad una lettura in +viene non ha più alcun effetto, mentre la seconda dà inizio ad una lettura in cache della regione del file indicata. La quantità di dati che verranno letti è ovviamente limitata in base al carico che si viene a creare sul sistema della memoria virtuale, ma in genere una lettura di qualche megabyte viene @@ -4608,11 +4644,12 @@ nuovi dati utili.\footnote{la pagina di manuale riporta l'esempio dello Sia \func{posix\_fadvise} che \func{readahead} attengono alla ottimizzazione dell'accesso in lettura; lo standard POSIX.1-2001 prevede anche una funzione -specifica per le operazioni di scrittura, \func{posix\_fallocate},\footnote{la - funzione è stata introdotta a partire dalle glibc 2.1.94.} che consente di -preallocare dello spazio disco per assicurarsi che una seguente scrittura non -fallisca, il suo prototipo, anch'esso disponibile solo se si definisce la -macro \macro{\_XOPEN\_SOURCE} ad almeno 600, è: +specifica per le operazioni di scrittura, +\funcd{posix\_fallocate},\footnote{la funzione è stata introdotta a partire + dalle glibc 2.1.94.} che consente di preallocare dello spazio disco per +assicurarsi che una seguente scrittura non fallisca, il suo prototipo, +anch'esso disponibile solo se si definisce la macro \macro{\_XOPEN\_SOURCE} ad +almeno 600, è: \begin{functions} \headdecl{fcntl.h} @@ -4639,35 +4676,58 @@ macro \macro{\_XOPEN\_SOURCE} ad almeno 600, } \end{functions} -La funzione si assicura che venga allocato sufficiente spazio disco perché sia +La funzione assicura che venga allocato sufficiente spazio disco perché sia possibile scrivere sul file indicato dall'argomento \param{fd} nella regione 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 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 - -Infine a partire dal kernel 2.6.23 è stata introdotta la nuova system call -\funcd{fallocate}, che consente di realizzare direttamente all'interno del -kernel le funzionalità di \func{posix\_fallocate}. Trattandosi di una funzione -di servizio questa non è stata definita come funzione di libreria e pertanto -può essere invocata indirettamente con l'ausilio di \func{syscall} (vedi -sez.~\ref{sec:intro_syscall}; il suo prototipo è: - +se questa regione 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 successiva scrittura nella regione +indicata non fallirà per mancanza di spazio disco. La funzione non ha nessun +effetto né sul contenuto, né sulla posizione corrente del file. + +Ci si può chiedere a cosa possa servire una funzione come +\func{posix\_fallocate} dato che è sempre possibile ottenere l'effetto voluto +eseguendo esplicitamente sul file la scrittura\footnote{usando \funcd{pwrite} + per evitare spostamenti della posizione corrente sul file.} di una serie di +zeri per l'estensione di spazio necessaria qualora il \itindex{sparse~file} +file debba essere esteso o abbia dei \index{file!\textit{hole}} +buchi.\footnote{si ricordi che occorre scrivere per avere l'allocazione e che + l'uso di \func{truncate} per estendere un file creerebbe soltanto uno + \itindex{sparse~file} \textit{sparse file} (vedi sez.~\ref{sec:file_lseek}) + senza una effettiva allocazione dello spazio disco.} In realtà questa è la +modalità con cui la funzione veniva realizzata nella prima versione fornita +dalle \acr{glibc}, per cui la funzione costituiva in sostanza soltanto una +standardizzazione delle modalità di esecuzione di questo tipo di allocazioni. + +Questo metodo, anche se funzionante, comporta però l'effettiva esecuzione una +scrittura su tutto lo spazio disco necessario, da fare al momento della +richiesta di allocazione, pagandone il conseguente prezzo in termini di +prestazioni; il tutto quando in realtà servirebbe solo poter riservare lo +spazio per poi andarci a scrivere, una sola volta, quando il contenuto finale +diventa effettivamente disponibile. + +Per poter fare tutto questo è però necessario il supporto da parte del kernel, +e questo è divenuto disponibile solo a partire dal kernel 2.6.23 in cui è +stata introdotta la nuova \textit{system call} \func{fallocate},\footnote{non + è detto che la funzione sia disponibile per tutti i filesystem, ad esempio + per XFS il supporto è stato introdotto solo a partire dal kernel 2.6.25.} +che consente di realizzare direttamente all'interno del kernel l'allocazione +dello spazio disco così da poter realizzare una versione di +\func{posix\_fallocate} con prestazioni molto più elevate.\footnote{nelle + \acr{glibc} la nuova \textit{system call} viene sfruttata per la + realizzazione di \func{posix\_fallocate} a partire dalla versione 2.10.} + +Trattandosi di una funzione di servizio, ed ovviamente disponibile +esclusivamente su Linux, inizialmente \funcd{fallocate} non era stata definita +come funzione di libreria,\footnote{pertanto poteva essere invocata soltanto + in maniera indiretta con l'ausilio di \func{syscall}, vedi + sez.~\ref{sec:intro_syscall}, come \code{long fallocate(int fd, int mode, + loff\_t offset, loff\_t len)}.} ma a partire dalle \acr{glibc} 2.10 è + stato fornito un supporto esplicito; il suo prototipo è: \begin{functions} - \headdecl{linux/falloc.h} - \funcdecl{long fallocate(int fd, int mode, loff\_t offset, loff\_t len)} + \headdecl{linux/fcntl.h} + + \funcdecl{int fallocate(int fd, int mode, off\_t offset, off\_t len)} Prealloca dello spazio disco per un file. @@ -4692,6 +4752,25 @@ sez.~\ref{sec:intro_syscall}; il suo prototipo } \end{functions} +La funzione prende gli stessi argomenti di \func{posix\_fallocate} con lo +stesso significato, a cui si aggiunge l'argomento \param{mode} che indica le +modalità di allocazione; al momento quest'ultimo può soltanto essere nullo o +assumere il valore \const{FALLOC\_FL\_KEEP\_SIZE} che richiede che la +dimensione del file\footnote{quella ottenuta nel campo \var{st\_size} di una + struttura \struct{stat} dopo una chiamata a \texttt{fstat}.} non venga +modificata anche quando la somma di \param{offset} e \param{len} eccede la +dimensione corrente. + +Se \param{mode} è nullo invece la dimensione totale del file in caso di +estensione dello stesso viene aggiornata, come richiesto per +\func{posix\_fallocate}, ed invocata in questo modo si può considerare +\func{fallocate} come l'implementazione ottimale di \func{posix\_fallocate} a +livello di kernel. + +% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/ +% http://kernelnewbies.org/Linux_2_6_23 + + %\subsection{L'utilizzo delle porte di I/O} @@ -4731,7 +4810,7 @@ sez.~\ref{sec:intro_syscall}; il suo prototipo % LocalWords: only ETXTBSY DENYWRITE ENODEV filesystem EPERM EXEC noexec table % LocalWords: ENFILE lenght segment violation SIGSEGV FIXED msync munmap copy % LocalWords: DoS Denial Service EXECUTABLE NORESERVE LOCKED swapping stack fs -% LocalWords: GROWSDOWN ANON GiB POPULATE prefaulting SIGBUS fifo VME fork old +% LocalWords: GROWSDOWN ANON POPULATE prefaulting SIGBUS fifo VME fork old % LocalWords: exec atime ctime mtime mprotect addr EACCESS mremap address new % LocalWords: long MAYMOVE realloc VMA virtual Ingo Molnar remap pages pgoff % LocalWords: dall' fault cache linker prelink advisory discrectionary lock fl @@ -4753,7 +4832,8 @@ sez.~\ref{sec:intro_syscall}; il suo prototipo % LocalWords: nwrite segs patch readahead posix fadvise TC advice FADV NORMAL % LocalWords: SEQUENTIAL NOREUSE WILLNEED DONTNEED streaming fallocate EFBIG % LocalWords: POLLRDHUP half close pwait Gb madvise MADV ahead REMOVE tmpfs -% LocalWords: DONTFORK DOFORK shmfs preadv pwritev syscall linux loff +% LocalWords: DONTFORK DOFORK shmfs preadv pwritev syscall linux loff head XFS +% LocalWords: MERGEABLE EOVERFLOW prealloca hole FALLOC KEEP stat fstat %%% Local Variables: