descriptor (anche nullo) che sono attivi, e -1 in caso di errore, nel qual
caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
+ \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato in uno
degli insiemi.
- \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
- \item[\errcode{EINVAL}] Si è specificato per \param{ndfs} un valore negativo
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] si è specificato per \param{ndfs} un valore negativo
o un valore non valido per \param{timeout}.
\end{errlist}
ed inoltre \errval{ENOMEM}.
descriptor (anche nullo) che sono attivi, e -1 in caso di errore, nel qual
caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
+ \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato in uno
degli insiemi.
- \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
- \item[\errcode{EINVAL}] Si è specificato per \param{ndfs} un valore negativo
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] si è specificato per \param{ndfs} un valore negativo
o un valore non valido per \param{timeout}.
\end{errlist}
ed inoltre \errval{ENOMEM}.}
in caso di successo, o 0 se c'è stato un timeout e -1 in caso di errore,
ed in quest'ultimo caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
+ \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato in uno
degli insiemi.
- \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
- \item[\errcode{EINVAL}] Il valore di \param{nfds} eccede il limite
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] il valore di \param{nfds} eccede il limite
\macro{RLIMIT\_NOFILE}.
\end{errlist}
ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
in caso di successo, o 0 se c'è stato un timeout e -1 in caso di errore,
ed in quest'ultimo caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
+ \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato in uno
degli insiemi.
- \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
- \item[\errcode{EINVAL}] Il valore di \param{nfds} eccede il limite
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] il valore di \param{nfds} eccede il limite
\macro{RLIMIT\_NOFILE}.
\end{errlist}
ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
sotto controllo. L'argomento viene ignorato con l'operazione
\const{EPOLL\_CTL\_DEL}.\footnote{fino al kernel 2.6.9 era comunque richiesto
che questo fosse un puntatore valido, anche se poi veniva ignorato, a
- partire dal 2.6.9 si può specificare anche anche un valore \texttt{NULL}.}
+ partire dal 2.6.9 si può specificare anche un valore \texttt{NULL}.}
(analogo di \const{POLLIN}).\\
\const{EPOLLOUT} & Il file è pronto per le operazioni di scrittura
(analogo di \const{POLLOUT}).\\
- \const{EPOLLRDHUP} & l'altro capo di un socket di tipo
+ \const{EPOLLRDHUP} & L'altro capo di un socket di tipo
\const{SOCK\_STREAM} (vedi sez.~\ref{sec:sock_type})
ha chiuso la connessione o il capo in scrittura
della stessa (vedi sez.~\ref{sec:TCP_shutdown}).\\
(operazione che può essere molto onerosa quando una directory contiene un gran
numero di file). Infine l'uso dei segnali come interfaccia di notifica
comporta tutti i problemi di gestione visti in sez.~\ref{sec:sig_management} e
-sez.~\ref{sec:sig_control}. Per tutta questa serie di motivi in generale
+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!inotify|)}
-% TODO inserire anche eventfd (vedi http://lwn.net/Articles/233462/)
-% e le restanti signalfd e timerfd introdotte con il 2.6.22
-% o trovargli un posto migliore
-
-
\subsection{L'interfaccia POSIX per l'I/O asincrono}
\label{sec:file_asyncronous_io}
\begin{figure}[!htb]
\centering
- \includegraphics[width=13cm]{img/mmap_boundary}
+ \includegraphics[height=6cm]{img/mmap_boundary}
\caption{Schema della mappatura in memoria di una sezione di file di
dimensioni non corrispondenti al bordo di una pagina.}
\label{fig:file_mmap_boundary}
\begin{figure}[htb]
\centering
- \includegraphics[width=13cm]{img/mmap_exceed}
+ \includegraphics[height=6cm]{img/mmap_exceed}
\caption{Schema della mappatura in memoria di file di dimensioni inferiori
alla lunghezza richiesta.}
\label{fig:file_mmap_exceed}
\itindend{memory~mapping}
-
-
\subsection{I/O vettorizzato: \func{readv} e \func{writev}}
\label{sec:file_multiple_io}
caratteristiche del funzionamento della funzione; il contenuto è una maschera
binaria e deve essere specificato come OR aritmetico dei valori riportati in
tab.~\ref{tab:splice_flag}. Alcuni di questi valori vengono utilizzati anche
-dalle funzioni \func{vmslice} e \func{tee} per cui la tabella riporta le
+dalle funzioni \func{vmsplice} e \func{tee} per cui la tabella riporta le
descrizioni complete di tutti i valori possibili anche quando, come per
\const{SPLICE\_F\_GIFT}, questi non hanno effetto su \func{splice}.
socket.\footnotemark Attualmente viene usato
solo da \func{splice}, potrà essere
implementato in futuro anche per
- \func{vmslice} e \func{tee}.\\
+ \func{vmsplice} e \func{tee}.\\
\const{SPLICE\_F\_GIFT} & Le pagine di memoria utente sono
``\textsl{donate}'' al kernel;\footnotemark
se impostato una seguente \func{splice} che
\hline
\end{tabular}
\caption{Le costanti che identificano i bit della maschera binaria
- dell'argomento \param{flags} di \func{slice}, \func{vmslice} e \func{tee}.}
+ dell'argomento \param{flags} di \func{splice}, \func{vmsplice} e
+ \func{tee}.}
\label{tab:splice_flag}
\end{table}
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 comunque copiate.}
+ comunque copiate.}
\footnotetext{questa opzione consente di utilizzare delle opzioni di gestione
dei socket che permettono di ottimizzare le trasmissioni via rete, si veda
(\texttt{\small 18--22}), quello di destinazione (\texttt{\small 23--27}) ed
infine (\texttt{\small 28--31}) la \textit{pipe} che verrà usata come buffer.
-
-\begin{figure}[!htbp]
+\begin{figure}[!phtb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
\includecodesample{listati/splicecp.c}
\label{fig:splice_example}
\end{figure}
-Il ciclo principale (\texttt{\small 33--59}) inizia con la lettura dal file
+Il ciclo principale (\texttt{\small 33--58}) inizia con la lettura dal file
sorgente tramite la prima \func{splice} (\texttt{\small 34--35}), in questo
caso si è usato come primo argomento il file descriptor del file sorgente e
come terzo quello del capo in scrittura della \textit{pipe} (il funzionamento
-delle \textit{pipe} è trattato in dettaglio in sez.~\ref{sec:ipc_unix},
-nell'ottica dell'uso di \func{splice} questa operazione corrisponde
-semplicemente alla copia dei dati dal file al buffer).
+delle \textit{pipe} e l'uso della coppia di file descriptor ad esse associati
+è trattato in dettaglio in sez.~\ref{sec:ipc_unix}; non ne parleremo qui dato
+che nell'ottica dell'uso di \func{splice} questa operazione corrisponde
+semplicemente al trasferimento dei dati dal file al buffer).
La lettura viene eseguita in blocchi pari alla dimensione specificata
dall'opzione \texttt{-s} (il default è 4096); essendo in questo caso
\func{splice} equivalente ad una \func{read} sul file, se ne controlla il
valore di uscita in \var{nread} che indica quanti byte sono stati letti, se
-nullo (\texttt{\small 36}) questo significa che si è giunti alla fine del file
-sorgente e pertanto l'operazione di copia è conclusa e si può uscire dal
-ciclo. In caso di valore negativo c'è stato un errore ed allora si ripete la
-lettura se questo è dovuto ad una interruzione, o si esce altrimenti
-(\texttt{\small 37--44}).
+detto valore è nullo (\texttt{\small 36}) questo significa che si è giunti
+alla fine del file sorgente e pertanto l'operazione di copia è conclusa e si
+può uscire dal ciclo arrivando alla conclusione del programma (\texttt{\small
+ 59}). In caso di valore negativo (\texttt{\small 37--44}) c'è stato un
+errore ed allora si ripete la lettura (\texttt{\small 36}) se questo è dovuto
+ad una interruzione, o altrimenti si esce con un messaggio di errore
+(\texttt{\small 41--43}).
Una volta completata con successo la lettura si avvia il ciclo di scrittura
-(\texttt{\small 45--58}); questo inizia (\texttt{\small 46--47}) con la
+(\texttt{\small 45--57}); questo inizia (\texttt{\small 46--47}) con la
seconda \func{splice} che cerca di scrivere gli \var{nread} byte letti, si
-noti come in questo caso il primo argomento sia il capo in lettura della
-\textit{pipe} ed il terzo il file descriptor del file di destinazione.
+noti come in questo caso il primo argomento faccia di nuovo riferimento alla
+\textit{pipe} (in questo caso si usa il capo in lettura, per i dettagli si
+veda al solito sez.~\ref{sec:ipc_unix}) mentre il terzo sia il file descriptor
+del file di destinazione.
Di nuovo si controlla il numero di byte effettivamente scritti restituito in
-\var{nwrite} e se nullo (\texttt{\small 48}) si ripete la scrittura (in realtà
-questo non avverrà mai), in caso di errore (\texttt{\small 49--56}) al solito
-si ripete la scrittura se questo è dovuto a una interruzione o si esce con un
-messaggio negli altri casi.
-
-Infine si chiude il ciclo di scrittura sottraendo (\texttt{\small 57}) il
-numero di byte scritti a quelli letti, così che il ciclo di scrittura venga
-ripetuto (\texttt{\small 58}) qualora la chiamata a \func{splice} non abbia
-esaurito tutti i dati presenti sul buffer.
+\var{nwrite} e in caso di errore al solito si ripete la scrittura se questo è
+dovuto a una interruzione o si esce con un messaggio negli altri casi
+(\texttt{\small 48--55}). Infine si chiude il ciclo di scrittura sottraendo
+(\texttt{\small 57}) il numero di byte scritti a quelli di cui è richiesta la
+scrittura,\footnote{in questa parte del ciclo \var{nread}, il cui valore
+ iniziale è dato dai byte letti dalla precedente chiamata a \func{splice},
+ viene ad assumere il significato di byte da scrivere.} così che il ciclo di
+scrittura venga ripetuto fintanto che il valore risultante sia maggiore di
+zero, indice che la chiamata a \func{splice} non ha esaurito tutti i dati
+presenti sul buffer.
Si noti come il programma sia concettualmente identico a quello che si sarebbe
-scritto usando \func{read} al posto della prima \func{splice} e \func{write} al
-posto della seconda, utilizzando un buffer in user space per eseguire la copia
-dei file, solo che in questo caso non è stato necessario allocare nessun
+scritto usando \func{read} al posto della prima \func{splice} e \func{write}
+al posto della seconda, utilizzando un buffer in user space per eseguire la
+copia dei dati, solo che in questo caso non è stato necessario allocare nessun
buffer e non si è trasferito nessun dato in user space.
+Si noti anche come si sia usata la combinazione \texttt{SPLICE\_F\_MOVE |
+ SPLICE\_F\_MORE } per l'argomento \param{flags} di \func{splice}, infatti
+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
+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.
+
+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 è:
+\begin{functions}
+ \headdecl{fcntl.h}
+ \headdecl{sys/uio.h}
+
+ \funcdecl{long vmsplice(int fd, const struct iovec *iov, unsigned long
+ nr\_segs, unsigned int flags)}
+
+ Trasferisce dati dalla memoria di un processo verso una \textit{pipe}.
+
+ \bodydesc{La funzione restituisce il numero di byte trasferiti in caso di
+ successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
+ dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] o \param{fd} non è un file descriptor valido o non
+ fa riferimento ad una \textit{pipe}.
+ \item[\errcode{EINVAL}] si è usato un valore nullo per \param{nr\_segs}
+ oppure si è usato \const{SPLICE\_F\_GIFT} ma la memoria non è allineata.
+ \item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'operazione
+ richiesta.
+ \end{errlist}
+ }
+\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}.
+
+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.
+
+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
+permette di duplicare i dati in ingresso su una \textit{pipe} su un'altra
+\textit{pipe}. In sostanza, sempre nell'ottica della manipolazione dei dati su
+dei buffer in kernel space, la funzione consente di eseguire una copia del
+contenuto del buffer stesso. Il prototipo di \funcd{tee} è il seguente:
+\begin{functions}
+ \headdecl{fcntl.h}
+
+ \funcdecl{long tee(int fd\_in, int fd\_out, size\_t len, unsigned int
+ flags)}
+
+ Duplica \param{len} byte da una \textit{pipe} ad un'altra.
+
+ \bodydesc{La funzione restituisce il numero di byte copiati in caso di
+ successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
+ dei valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] o uno fra \param{fd\_in} e \param{fd\_out} non fa
+ riferimento ad una \textit{pipe} o entrambi fanno riferimento alla
+ stessa \textit{pipe}.
+ \item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'operazione
+ richiesta.
+ \end{errlist}
+ }
+\end{functions}
+
+La funzione copia \param{len} byte del contenuto di una \textit{pipe} su di
+un'altra; \param{fd\_in} deve essere il capo in lettura della \textit{pipe}
+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}).
+
+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
+byte disponibili da copiare e che il capo in scrittura della pipe è stato
+chiuso.\footnote{si tenga presente però che questo non avviene se si è
+ impostato il flag \const{SPLICE\_F\_NONBLOCK}, in tal caso infatti si
+ avrebbe un errore di \errcode{EAGAIN}.} Un esempio di realizzazione del
+comando \texttt{tee} usando questa funzione, ripreso da quello fornito nella
+pagina di manuale e dall'esempio allegato al patch originale, è riportato in
+fig.~\ref{fig:tee_example}. Il programma consente di copiare il contenuto
+dello standard input sullo standard output e su un file specificato come
+argomento, il codice completo si trova nel file \texttt{tee.c} dei sorgenti
+allegati alla guida.
-% TODO documentare le funzioni tee e splice
-% http://kerneltrap.org/node/6505 e http://lwn.net/Articles/178199/ e
-% http://lwn.net/Articles/179492/
-% e http://en.wikipedia.org/wiki/Splice_(system_call)
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/tee.c}
+ \end{minipage}
+ \normalsize
+ \caption{Esempio di codice che usa \func{tee} per copiare i dati dello
+ standard input sullo standard output e su un file.}
+ \label{fig:tee_example}
+\end{figure}
+La prima parte del programma (\texttt{\small 10--35}) si cura semplicemente di
+controllare (\texttt{\small 11--14}) che sia stato fornito almeno un argomento
+(il nome del file su cui scrivere), di aprirlo ({\small 15--19}) e che sia lo
+standard input (\texttt{\small 20--27}) che lo standard output (\texttt{\small
+ 28--35}) corrispondano ad una \textit{pipe}.
+
+Il ciclo principale (\texttt{\small 37--58}) inizia con la chiamata a
+\func{tee} che duplica il contenuto dello standard input sullo standard output
+(\texttt{\small 39}), questa parte è del tutto analoga ad una lettura ed
+infatti come nell'esempio di fig.~\ref{fig:splice_example} si controlla il
+valore di ritorno della funzione in \var{len}; se questo è nullo significa che
+non ci sono più dati da leggere e si chiude il ciclo (\texttt{\small 40}), se
+è negativo c'è stato un errore, ed allora si ripete la chiamata se questo è
+dovuto ad una interruzione (\texttt{\small 42--44}) o si stampa un messaggio
+di errore e si esce negli altri casi (\texttt{\small 44--47}).
+
+Una volta completata la copia dei dati sullo standard output si possono
+estrarre dalla standard input e scrivere sul file, di nuovo su usa un ciclo di
+scrittura (\texttt{\small 50--58}) in cui si ripete una chiamata a
+\func{splice} (\texttt{\small 51}) fintanto che non si sono scritti tutti i
+\var{len} byte copiati in precedenza con \func{tee} (il funzionamento è
+identico all'analogo ciclo di scrittura del precedente esempio di
+fig.~\ref{fig:splice_example}).
+
+Infine una nota finale riguardo \func{splice}, \func{vmsplice} e \func{tee}:
+occorre sottolineare che benché finora si sia parlato di trasferimenti o copie
+di dati in realtà nella implementazione di queste system call non è affatto
+detto che i dati vengono effettivamente spostati o copiati, il kernel infatti
+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
+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.
verranno usati i file, possono necessitare di effettuare delle ottimizzazioni
specifiche, relative alle proprie modalità di I/O sugli stessi. Tratteremo in
questa sezione una serie funzioni che consentono ai programmi di ottimizzare
-il loro accesso ai dati dei file.
+il loro accesso ai dati dei file e controllare la gestione del relativo
+\textit{caching}.
+
+Una prima funzione che può essere utilizzata per modificare la gestione
+ordinaria dell'I/O su file è \funcd{readahead},\footnote{questa è una funzione
+ specifica di Linux, introdotta con il kernel 2.4.13, e non deve essere usata
+ se si vogliono scrivere programmi portabili.} che consente di richiedere una
+lettura anticipata del contenuto dello stesso in modo da riempire la memoria
+di cache, così che le seguenti operazioni di lettura non debbano bloccarsi
+nell'I/O su disco, il suo prototipo è:
+\begin{functions}
+ \headdecl{fcntl.h}
+
+ \funcdecl{ssize\_t readahead(int fd, off64\_t *offset, size\_t count)}
+
+ Legge il contenuto di un file nella cache di memoria.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] l'argomento \param{fd} non è un file descriptor
+ valido o non è aperto in lettura.
+ \item[\errcode{EINVAL}] l'argomento \param{fd} si riferisce ad un tipo di
+ file che non supporta l'operazione (come una pipe o un socket).
+ \end{errlist}
+ }
+\end{functions}
+
+La funzione richiede che sul file \param{fd}, a partire dalla posizione
+\param{offset}, venga letto in anticipo il contenuto, portandolo nella cache
+della memoria virtuale, per un ammontare di \param{count} bytes. La funzione
+usa la memoria virtuale ed il meccanismo della paginazione per cui la lettura
+verrà eseguita in blocchi corrispondenti alle dimensioni delle pagine di
+memoria, ed i valori di \param{offset} e \param{count} arrotondati di
+conseguenza.
+
+La funzione esegue la lettura bloccandosi 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
+interromperà 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.
+
+Il concetto di \func{readahead} viene generalizzato nello standard
+POSIX.1-2001 dalla funzione \funcd{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, è:
+\begin{functions}
+ \headdecl{fcntl.h}
+
+ \funcdecl{int posix\_fadvise(int fd, off\_t offset, off\_t len, int advice)}
+
+ Dichiara al kernel le future modalità di accesso ad un file.
+
+ \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}
+ \item[\errcode{EBADF}] l'argomento \param{fd} non è un file descriptor
+ valido.
+ \item[\errcode{EINVAL}] il valore di \param{advice} non è valido o
+ \param{fd} si riferisce ad un tipo di file che non supporta l'operazione
+ (come una pipe o un socket).
+ \end{errlist}
+ \item[\errcode{ESPIPE}] previsto dallo standard se \param{fd} è una pipe o
+ un socket (ma su Linux viene restituito \errcode{EINVAL}).
+ }
+\end{functions}
+
+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
+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.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{10cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{POSIX\_FADV\_NORMAL} & Non ci sono avvisi specifici da fare
+ riguardo le modalità di accesso, il
+ comportamento sarà identico a quello che si
+ avrebbe senza nessun avviso.\\
+ \const{POSIX\_FADV\_SEQUENTIAL} & .\\
+ \const{POSIX\_FADV\_RANDOM} & .\\
+ \const{POSIX\_FADV\_NOREUSE} & .\\
+ \const{POSIX\_FADV\_WILLNEED} & .\\
+ \const{POSIX\_FADV\_DONTNEED} & .\\
+ \hline
+ \end{tabular}
+ \caption{Valori dei bit dell'argomento \param{advice} di
+ \func{posix\_fadvise} che indicano la modalità con cui si intende accedere
+ ad un file.}
+ \label{tab:posix_fadvise_flag}
+\end{table}
+
-% TODO documentare \func{madvise}
-% TODO documentare \func{mincore}
% TODO documentare \func{posix\_fadvise}
+% TODO documentare \func{readahead}
% vedi http://insights.oetiker.ch/linux/fadvise.html
% questo tread? http://www.ussg.iu.edu/hypermail/linux/kernel/0703.1/0032.html
output sul file.
In tutti questi casi il \textit{file locking} è la tecnica che permette di
-evitare le \textit{race condition} \itindex{race~condition}, attraverso una
+evitare le \itindex{race~condition} \textit{race condition}, attraverso una
serie di funzioni che permettono di bloccare l'accesso al file da parte di
altri processi, così da evitare le sovrapposizioni, e garantire la atomicità
delle operazioni di scrittura.
% LocalWords: EPOLLHUP EPOLLET EPOLLONESHOT shot maxevents ctlv ALL DONT HPUX
% LocalWords: FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching sysctl instances name
% LocalWords: watches IGNORED ISDIR OVERFLOW overflow UNMOUNT queued cookie ls
-% LocalWords: NUL sizeof casting printevent nread limits sysconf SC wrapper
-% LocalWords: splice result argument DMA controller zerocopy Linus
+% 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
%%% Local Variables: