Alcune correzioni ai font dei link, e una trattazione esplicita
[gapil.git] / fileadv.tex
index 330bed97ac81bd6bb049ee4953d822d6f7b51618..1ba5b9990692a8489fe8deefd1f9c54124dd4964 100644 (file)
@@ -107,10 +107,10 @@ Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
     descriptor (anche nullo) che sono attivi, e -1 in caso di errore, nel qual
     caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
     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.
     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}.
     o un valore non valido per \param{timeout}.
   \end{errlist}
   ed inoltre \errval{ENOMEM}.
@@ -267,10 +267,10 @@ precedenti, ed inoltre aggiunge a \func{select} una nuova funzione
     descriptor (anche nullo) che sono attivi, e -1 in caso di errore, nel qual
     caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
     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.
     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}.}
     o un valore non valido per \param{timeout}.
   \end{errlist}
   ed inoltre \errval{ENOMEM}.}
@@ -350,10 +350,10 @@ cui prototipo 
     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}
     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.
     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}.}
     \macro{RLIMIT\_NOFILE}.
   \end{errlist}
   ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
@@ -410,13 +410,13 @@ nel campo \var{revents} per notificare delle condizioni di errore.
     \hline
     \const{POLLIN}    & È possibile la lettura.\\
     \const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\ 
     \hline
     \const{POLLIN}    & È possibile la lettura.\\
     \const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\ 
-    \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari. \\
+    \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari.\\
     \const{POLLPRI}   & È possibile la lettura di \itindex{out-of-band} dati
                         urgenti.\\ 
     \hline
     \const{POLLOUT}   & È possibile la scrittura immediata.\\
     \const{POLLPRI}   & È possibile la lettura di \itindex{out-of-band} dati
                         urgenti.\\ 
     \hline
     \const{POLLOUT}   & È possibile la scrittura immediata.\\
-    \const{POLLWRNORM}& È possibile la scrittura di dati normali.  \\ 
-    \const{POLLWRBAND}& È possibile la scrittura di dati prioritari. \\
+    \const{POLLWRNORM}& È possibile la scrittura di dati normali.\\ 
+    \const{POLLWRBAND}& È possibile la scrittura di dati prioritari.\\
     \hline
     \const{POLLERR}   & C'è una condizione di errore.\\
     \const{POLLHUP}   & Si è verificato un hung-up.\\
     \hline
     \const{POLLERR}   & C'è una condizione di errore.\\
     \const{POLLHUP}   & Si è verificato un hung-up.\\
@@ -496,10 +496,10 @@ prototipo 
     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}
     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.
     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}.}
     \macro{RLIMIT\_NOFILE}.
   \end{errlist}
   ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
@@ -668,15 +668,15 @@ delle operazioni cui fanno riferimento.
     \textbf{Valore}  & \textbf{Significato} \\
     \hline
     \hline
     \textbf{Valore}  & \textbf{Significato} \\
     \hline
     \hline
-    \const{EPOLL\_CTL\_ADD}& aggiunge un nuovo file descriptor da osservare
+    \const{EPOLL\_CTL\_ADD}& Aggiunge un nuovo file descriptor da osservare
                              \param{fd} alla lista dei file descriptor
                              controllati tramite \param{epfd}, in
                              \param{event} devono essere specificate le
                              modalità di osservazione.\\
                              \param{fd} alla lista dei file descriptor
                              controllati tramite \param{epfd}, in
                              \param{event} devono essere specificate le
                              modalità di osservazione.\\
-    \const{EPOLL\_CTL\_MOD}& modifica le modalità di osservazione del file
+    \const{EPOLL\_CTL\_MOD}& Modifica le modalità di osservazione del file
                              descriptor \param{fd} secondo il contenuto di
                              \param{event}.\\
                              descriptor \param{fd} secondo il contenuto di
                              \param{event}.\\
-    \const{EPOLL\_CTL\_DEL}& rimuove il file descriptor \param{fd} dalla lista
+    \const{EPOLL\_CTL\_DEL}& Rimuove il file descriptor \param{fd} dalla lista
                              dei file controllati tramite \param{epfd}.\\
     \hline    
   \end{tabular}
                              dei file controllati tramite \param{epfd}.\\
     \hline    
   \end{tabular}
@@ -699,7 +699,7 @@ indicare quale tipo di evento relativo ad \param{fd} si vuole che sia tenuto
 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
 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}.}
 
 
 
 
 
 
@@ -741,7 +741,7 @@ si usa come valore lo stesso \param{fd}.
                           (analogo di \const{POLLIN}).\\
     \const{EPOLLOUT}    & Il file è pronto per le operazioni di scrittura
                           (analogo di \const{POLLOUT}).\\
                           (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}).\\
                           \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}).\\
@@ -848,38 +848,45 @@ La funzione ritorna il numero di eventi rilevati, o un valore nullo qualora
 sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo,
 oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che
 indica di non attendere e ritornare immediatamente,\footnote{anche in questo
 sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo,
 oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che
 indica di non attendere e ritornare immediatamente,\footnote{anche in questo
-  caso il valore di ritorno sarà nullo.} o $-1$, che indica un'attesa
-indefinita. L'argomento \param{maxevents} dovrà invece essere sempre un intero
-positivo.
+  caso il valore di ritorno sarà nullo.} o il valore $-1$, che indica
+un'attesa indefinita. L'argomento \param{maxevents} dovrà invece essere sempre
+un intero positivo.
 
 Come accennato la funzione restituisce i suoi risultati nel vettore di
 strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel
 campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli
 eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era
 
 Come accennato la funzione restituisce i suoi risultati nel vettore di
 strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel
 campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli
 eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era
-stato impostato (per il file descriptor per cui si è verificato l'evento)
-quando questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
-\const{EPOLL\_CTL\_ADD}.
+stato impostato per il file descriptor per cui si è verificato l'evento quando
+questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
+\const{EPOLL\_CTL\_ADD}, in questo modo il campo \var{data} consente di
+identificare il file descriptor.\footnote{ed è per questo che, come accennato,
+  è consuetudine usare per \var{data} il valore del file descriptor stesso.}
 
 Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da
 come si è impostata la modalità di osservazione (se \textit{level triggered} o
 \textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura
 che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait}
 
 Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da
 come si è impostata la modalità di osservazione (se \textit{level triggered} o
 \textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura
 che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait}
-questi vengano combinati. Inoltre qualora su di esso fossero presenti eventi
-non ancora notificati, e si effettuasse una modifica dell'osservazione con
-\const{EPOLL\_CTL\_MOD} questi verrebbero riletti alla luce delle modifiche.
+questi vengano combinati. Inoltre qualora su un file descriptor fossero
+presenti eventi non ancora notificati, e si effettuasse una modifica
+dell'osservazione con \const{EPOLL\_CTL\_MOD} questi verrebbero riletti alla
+luce delle modifiche.
 
 Si tenga presente infine che con l'uso della modalità \textit{edge triggered}
 il ritorno di \func{epoll\_wait} indica un file descriptor è pronto e resterà
 
 Si tenga presente infine che con l'uso della modalità \textit{edge triggered}
 il ritorno di \func{epoll\_wait} indica un file descriptor è pronto e resterà
-tale fintanto che non si sono completamente esaurite le operazioni su di esso,
-questo può essere rilevato con un errore di \errcode{EAGAIN} in una
-\func{read} o una \func{write},\footnote{è opportuno ricordare ancora una
-  volta che l'uso dell'I/O multiplexing richiede di operare sui file in
-  modalità non bloccante.} ma anche con il fatto che sono stati restituiti
-meno dati di quelli richiesti.
-
-Come per le precedenti \func{select} e \func{poll}, essendo queste funzioni
-utiilizzate prevalentemente con i server di rete, tratteremo degli esempi del
-loro più avanti, nella trattazione dei socket, ed in particolare in
+tale fintanto che non si sono completamente esaurite le operazioni su di esso.
+Questa condizione viene generalmente rilevata dall'occorrere di un errore di
+\errcode{EAGAIN} al ritorno di una \func{read} o una \func{write},\footnote{è
+  opportuno ricordare ancora una volta che l'uso dell'I/O multiplexing
+  richiede di operare sui file in modalità non bloccante.} ma questa non è la
+sola modalità possibile, ad esempio la condizione può essere riconosciuta
+anche con il fatto che sono stati restituiti meno dati di quelli richiesti.
+
+Come le precedenti \func{select} e \func{poll}, le funzioni dell'interfaccia
+di \textit{epoll} vengono utilizzate prevalentemente con i server di rete,
+quando si devono tenere sotto osservazione un gran numero di socket; per
+questo motivo rimandiamo di nuovo la trattazione di un esempio concreto a
+quando avremo esaminato in dettaglio le caratteristiche dei socket, in
+particolare si potrà trovare un programma che utilizza questa interfaccia in
 sez.~\ref{sec:TCP_sock_multiplexing}.
 
 
 sez.~\ref{sec:TCP_sock_multiplexing}.
 
 
@@ -989,8 +996,8 @@ diventati attivi. L'unico modo per essere sicuri che questo non avvenga 
 impostare la lunghezza della coda dei segnali real-time ad una dimensione
 identica al valore massimo del numero di file descriptor
 utilizzabili.\footnote{vale a dire impostare il contenuto di
 impostare la lunghezza della coda dei segnali real-time ad una dimensione
 identica al valore massimo del numero di file descriptor
 utilizzabili.\footnote{vale a dire impostare il contenuto di
-  \texttt{/proc/sys/kernel/rtsig-max} allo stesso valore di quello di
-  \texttt{/proc/sys/fs/file-max}.}
+  \procfile{/proc/sys/kernel/rtsig-max} allo stesso valore del contenuto di
+  \procfile{/proc/sys/fs/file-max}.}
 
 % TODO fare esempio che usa O_ASYNC
 
 
 % TODO fare esempio che usa O_ASYNC
 
@@ -1004,27 +1011,29 @@ risposta\footnote{o meglio la non risposta, tanto che questa nelle Unix FAQ
   \cite{UnixFAQ} viene anche chiamata una \textit{Frequently Unanswered
     Question}.} è che nell'architettura classica di Unix questo non è
 possibile. Al contrario di altri sistemi operativi infatti un kernel unix-like
   \cite{UnixFAQ} viene anche chiamata una \textit{Frequently Unanswered
     Question}.} è che nell'architettura classica di Unix questo non è
 possibile. Al contrario di altri sistemi operativi infatti un kernel unix-like
-non prevede alcun meccanismo per cui un processo possa essere
+classico non prevedeva alcun meccanismo per cui un processo possa essere
 \textsl{notificato} di eventuali modifiche avvenute su un file. Questo è il
 motivo per cui i demoni devono essere \textsl{avvisati} in qualche
 modo\footnote{in genere questo vien fatto inviandogli un segnale di
 \textsl{notificato} di eventuali modifiche avvenute su un file. Questo è il
 motivo per cui i demoni devono essere \textsl{avvisati} in qualche
 modo\footnote{in genere questo vien fatto inviandogli un segnale di
-  \const{SIGHUP} che, per convenzione adottata dalla gran parte di detti
+  \const{SIGHUP} che, per una convenzione adottata dalla gran parte di detti
   programmi, causa la rilettura della configurazione.} se il loro file di
 configurazione è stato modificato, perché possano rileggerlo e riconoscere le
 modifiche.
 
 Questa scelta è stata fatta perché provvedere un simile meccanismo a livello
   programmi, causa la rilettura della configurazione.} se il loro file di
 configurazione è stato modificato, perché possano rileggerlo e riconoscere le
 modifiche.
 
 Questa scelta è stata fatta perché provvedere un simile meccanismo a livello
-generale comporterebbe un notevole aumento di complessità dell'architettura
-della gestione dei file, per fornire una funzionalità necessaria soltanto in
-casi particolari. Dato che all'origine di Unix i soli programmi che potevano
-avere una tale esigenza erano i demoni, attenendosi a uno dei criteri base
-della progettazione, che era di far fare al kernel solo le operazioni
-strettamente necessarie e lasciare tutto il resto a processi in user space,
-non era stata prevista nessuna funzionalità di notifica.
+generico per qualunque file comporterebbe un notevole aumento di complessità
+dell'architettura della gestione dei file, il tutto per fornire una
+funzionalità che serve soltanto in alcuni casi particolari. Dato che
+all'origine di Unix i soli programmi che potevano avere una tale esigenza
+erano i demoni, attenendosi a uno dei criteri base della progettazione, che
+era di far fare al kernel solo le operazioni strettamente necessarie e
+lasciare tutto il resto a processi in user space, non era stata prevista
+nessuna funzionalità di notifica.
 
 Visto però il crescente interesse nei confronti di una funzionalità di questo
 
 Visto però il crescente interesse nei confronti di una funzionalità di questo
-tipo (molto richiesta specialmente nello sviluppo dei programmi ad interfaccia
-grafica) sono state successivamente introdotte delle estensioni che
+tipo, che è molto richiesta specialmente nello sviluppo dei programmi ad
+interfaccia grafica, quando si deve presentare all'utente lo stato del
+filesystem, sono state successivamente introdotte delle estensioni che
 permettessero la creazione di meccanismi di notifica più efficienti dell'unica
 soluzione disponibile con l'interfaccia tradizionale, che è quella del
 \itindex{polling} \textit{polling}.
 permettessero la creazione di meccanismi di notifica più efficienti dell'unica
 soluzione disponibile con l'interfaccia tradizionale, che è quella del
 \itindex{polling} \textit{polling}.
@@ -1136,7 +1145,7 @@ operazione di lettura, declassando il \textit{lease} a lettura con
 
 Se il \textit{lease holder} non provvede a rilasciare il \textit{lease} entro
 il numero di secondi specificato dal parametro di sistema mantenuto in
 
 Se il \textit{lease holder} non provvede a rilasciare il \textit{lease} entro
 il numero di secondi specificato dal parametro di sistema mantenuto in
-\file{/proc/sys/fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o
+\procfile{/proc/sys/fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o
 declassarlo) automaticamente.\footnote{questa è una misura di sicurezza per
   evitare che un processo blocchi indefinitamente l'accesso ad un file
   acquisendo un \textit{lease}.} Una volta che un \textit{lease} è stato
 declassarlo) automaticamente.\footnote{questa è una misura di sicurezza per
   evitare che un processo blocchi indefinitamente l'accesso ad un file
   acquisendo un \textit{lease}.} Una volta che un \textit{lease} è stato
@@ -1153,13 +1162,19 @@ risolvere il problema di rilevare automaticamente quando un file o una
 directory vengono modificati, che è quanto necessario ad esempio ai programma
 di gestione dei file dei vari desktop grafici.
 
 directory vengono modificati, che è quanto necessario ad esempio ai programma
 di gestione dei file dei vari desktop grafici.
 
-Per risolvere questo problema è stata allora creata un'altra interfaccia,
-chiamata \textit{dnotify}, che consente di richiedere una notifica quando una
-directory, o di uno qualunque dei file in essa contenuti, viene modificato.
-Come per i \textit{file lease} la notifica avviene di default attraverso il
-segnale \const{SIGIO}, ma se ne può utilizzare un altro. Inoltre si potrà
-ottenere nel gestore del segnale il file descriptor che è stato modificato
-tramite il contenuto della struttura \struct{siginfo\_t}.
+Per risolvere questo problema a partire dal kernel 2.4 è stata allora creata
+un'altra interfaccia,\footnote{si ricordi che anche questa è una interfaccia
+  specifica di Linux che deve essere evitata se si vogliono scrivere programmi
+  portabili, e che le funzionalità illustrate sono disponibili soltanto se è
+  stata definita la macro \macro{\_GNU\_SOURCE}.} chiamata \textit{dnotify},
+che consente di richiedere una notifica quando una directory, o uno qualunque
+dei file in essa contenuti, viene modificato.  Come per i \textit{file lease}
+la notifica avviene di default attraverso il segnale \const{SIGIO}, ma se ne
+può utilizzare un altro.\footnote{e di nuovo, per le ragioni già esposte in
+  precedenza, è opportuno che si utilizzino dei segnali real-time.} Inoltre,
+come in precedenza, si potrà ottenere nel gestore del segnale il file
+descriptor che è stato modificato tramite il contenuto della struttura
+\struct{siginfo\_t}.
 
 \index{file!lease|)}
 
 
 \index{file!lease|)}
 
@@ -1189,7 +1204,7 @@ tramite il contenuto della struttura \struct{siginfo\_t}.
     \const{DN\_ATTRIB} & È stato modificato un attributo di un file con
                          l'esecuzione di una fra \func{chown}, \func{chmod},
                          \func{utime}.\\ 
     \const{DN\_ATTRIB} & È stato modificato un attributo di un file con
                          l'esecuzione di una fra \func{chown}, \func{chmod},
                          \func{utime}.\\ 
-    \const{DN\_MULTISHOT}& richiede una notifica permanente di tutti gli
+    \const{DN\_MULTISHOT}& Richiede una notifica permanente di tutti gli
                          eventi.\\ 
     \hline    
   \end{tabular}
                          eventi.\\ 
     \hline    
   \end{tabular}
@@ -1221,30 +1236,34 @@ specificare un valore nullo.
 
 Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve
 usare un file descriptor per ciascuna directory che si vuole tenere sotto
 
 Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve
 usare un file descriptor per ciascuna directory che si vuole tenere sotto
-controllo, il che porta facilmente ad un eccesso di file aperti. Inoltre
-quando la directory è su un dispositivo rimovibile, mantenere un file
-descriptor aperto comporta l'impossibilità di smontare il dispositivo e
-rimuoverlo, complicando la gestione.
-
-Un secondo problema è che l'interfaccia consente solo di tenere sotto
-controllo il contenuto di una directory; la modifica di un file viene
-segnalata, ma poi devo verificare quale è.  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}, e per questo in
-generale quella di \textit{dnotify} viene considerata una interfaccia di
-usabilità problematica.
+controllo, il che porta facilmente ad avere un eccesso di file aperti. Inoltre
+quando la directory che si controlla è all'interno di un dispositivo
+rimovibile, mantenere il relativo file descriptor aperto comporta
+l'impossibilità di smontare il dispositivo e di rimuoverlo, il che in genere
+complica notevolmente la gestione dell'uso di questi dispositivi.
+
+Un altro problema è che l'interfaccia di \textit{dnotify} consente solo di
+tenere sotto controllo il contenuto di una directory; la modifica di un file
+viene segnalata, ma poi è necessario verificare di quale file si tratta
+(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_adv_control}.  Per tutta questa serie di motivi in generale
+quella di \textit{dnotify} viene considerata una interfaccia di usabilità
+problematica.
 
 \index{file!dnotify|)}
 
 
 \index{file!dnotify|)}
 
-Per questa serie di motivi, a partire dal kernel 2.6.13, è stata introdotta
-una nuova interfaccia per l'osservazione delle modifiche a file o directory,
-chiamata \textit{inotify}.\footnote{le corrispondenti funzioni di interfaccia
-  sono state introdotte nelle glibc 2.4.} Questa è una interfaccia specifica
-di Linux (pertanto non deve essere usata se si devono scrivere programmi
-portabili), ed è basata sull'uso di una coda di notifica degli eventi
-associata ad un singolo file descriptor, risolvendo così il principale
-problema di \itindex{dnotify} \textit{dnotify}. La coda viene creata
-attraverso la funzione \funcd{inotify\_init}, il cui prototipo è:
+Per risolvere i problemi appena illustrati è stata introdotta una nuova
+interfaccia per l'osservazione delle modifiche a file o directory, chiamata
+\textit{inotify}.\footnote{l'interfaccia è disponibile a partire dal kernel
+  2.6.13, le relative funzioni sono state introdotte nelle glibc 2.4.}  Anche
+questa è una interfaccia specifica di Linux (pertanto non deve essere usata se
+si devono scrivere programmi portabili), ed è basata sull'uso di una coda di
+notifica degli eventi associata ad un singolo file descriptor, il che permette
+di risolvere il principale problema di \itindex{dnotify} \textit{dnotify}.  La
+coda viene creata attraverso la funzione \funcd{inotify\_init}, il cui
+prototipo è:
 \begin{prototype}{sys/inotify.h}
   {int inotify\_init(void)}
   
 \begin{prototype}{sys/inotify.h}
   {int inotify\_init(void)}
   
@@ -1263,35 +1282,41 @@ attraverso la funzione \funcd{inotify\_init}, il cui prototipo 
 }
 \end{prototype}
 
 }
 \end{prototype}
 
-La funzione non prende alcun argomento, e restituisce un file descriptor
-associato alla coda, attraverso il quale verranno effettuate le operazioni di
-notifica. Si tratta di un file descriptor speciale, che non è associato a
-nessun file, ma che viene utilizzato per notificare gli eventi che si sono
-posti in osservazione all'applicazione che usa l'interfaccia di
-\textit{inotify}. Dato che questo file descriptor non è associato a nessun
-file o directory, questo consente di evitare l'inconveniente di non poter
-smontare un filesystem i cui file sono tenuti sotto osservazione.\footnote{ed
-  una delle caratteristiche dell'interfaccia di \textit{inotify} è proprio
-  quella di notificare il fatto che il filesystem su cui si trova il file o la
-  directory osservata è stato smontato.} 
+La funzione non prende alcun argomento; inizializza una istanza di
+\textit{inotify} e restituisce un file descriptor attraverso il quale verranno
+effettuate le operazioni di notifica;\footnote{per evitare abusi delle risorse
+  di sistema è previsto che un utente possa utilizzare un numero limitato di
+  istanze di \textit{inotify}; il valore di default del limite è di 128, ma
+  questo valore può essere cambiato con \func{sysctl} o usando il file
+  \procfile{/proc/sys/fs/inotify/max\_user\_instances}.} si tratta di un file
+descriptor speciale che non è associato a nessun file su disco, e che viene
+utilizzato solo per notificare gli eventi che sono stati posti in
+osservazione. Dato che questo file descriptor non è associato a nessun file o
+directory reale, l'inconveniente di non poter smontare un filesystem i cui
+file sono tenuti sotto osservazione viene completamente
+eliminato.\footnote{anzi, una delle capacità dell'interfaccia di
+  \textit{inotify} è proprio quella di notificare il fatto che il filesystem
+  su cui si trova il file o la directory osservata è stato smontato.}
 
 Inoltre trattandosi di un file descriptor a tutti gli effetti, esso potrà
 
 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 siccome gli eventi vengono notificati come dati disponibili in lettura sul
-file descriptor, dette funzioni ritorneranno tutte le volte che si avrà un
-evento di notifica. Così, invece di dover utilizzare i segnali, si potrà
-gestire l'osservazione delle modifiche con l'\textit{I/O multiplexing},
-utilizzando secondo le modalità illustrate in
-sez.~\ref{sec:file_multiplexing}.
+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
+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
+sez.~\ref{sec:file_multiplexing}. Qualora si voglia cessare l'osservazione,
+sarà sufficiente chiudere il file descriptor e tutte le risorse allocate
+saranno automaticamente rilasciate.
 
 Infine l'interfaccia di \textit{inotify} consente di mettere sotto
 
 Infine l'interfaccia di \textit{inotify} consente di mettere sotto
-osservazione sia singoli file, che intere directory; in quest'ultimo caso
-l'interfaccia restituirà informazioni sia riguardo alla directory che ai file
-che essa contiene.  Una volta creata la coda di notifica si devono definire
-gli eventi da tenere sotto osservazione; questo viene fatto tramite una
-\textsl{lista di osservazione} (o \textit{watch list}) associata alla coda.
-Per gestire la lista di osservazione l'interfaccia fornisce due funzioni, la
-prima di queste è \funcd{inotify\_add\_watch}, il cui prototipo è:
+osservazione, oltre che una directory, anche singoli file.  Una volta creata
+la coda di notifica si devono definire gli eventi da tenere sotto
+osservazione; questo viene fatto attraverso una \textsl{lista di osservazione}
+(o \textit{watch list}) che è associata alla coda. Per gestire la lista di
+osservazione l'interfaccia fornisce due funzioni, la prima di queste è
+\funcd{inotify\_add\_watch}, il cui prototipo è:
 \begin{prototype}{sys/inotify.h}
   {int inotify\_add\_watch(int fd, const char *pathname, uint32\_t mask)}
 
 \begin{prototype}{sys/inotify.h}
   {int inotify\_add\_watch(int fd, const char *pathname, uint32\_t mask)}
 
@@ -1302,23 +1327,36 @@ prima di queste 
   \begin{errlist}
   \item[\errcode{EACCESS}] non si ha accesso in lettura al file indicato.
   \item[\errcode{EINVAL}] \param{mask} non contiene eventi legali o \param{fd}
   \begin{errlist}
   \item[\errcode{EACCESS}] non si ha accesso in lettura al file indicato.
   \item[\errcode{EINVAL}] \param{mask} non contiene eventi legali o \param{fd}
-    non è un filesystem di \textit{inotify}.
+    non è un file descriptor di \textit{inotify}.
   \item[\errcode{ENOSPC}] si è raggiunto il numero massimo di voci di
     osservazione o il kernel non ha potuto allocare una risorsa necessaria.
   \end{errlist}
   ed inoltre \errval{EFAULT}, \errval{ENOMEM} e \errval{EBADF}.}
 \end{prototype}
 
   \item[\errcode{ENOSPC}] si è raggiunto il numero massimo di voci di
     osservazione o il kernel non ha potuto allocare una risorsa necessaria.
   \end{errlist}
   ed inoltre \errval{EFAULT}, \errval{ENOMEM} e \errval{EBADF}.}
 \end{prototype}
 
-La funzione consente di creare un \textsl{evento di osservazione} (un
-cosiddetto ``\textit{watch}'') nella lista di una coda di notifica, indicata
-specificando il file descriptor ad essa associato nell'argomento \param{fd}.
-Il file o la directory da porre sotto osservazione viene invece indicato per
-nome, che viene passato nell'argomento \param{pathname}. Infine il terzo
-argomento, \param{mask}, indica che tipo di eventi devono essere tenuti sotto
-osservazione. Questo deve essere specificato come maschera binaria combinando
-i valori delle costanti riportate in tab.~\ref{tab:inotify_event_watch}. In
-essa si sono marcati con un ``$\bullet$'' gli eventi che, quando specificati
-per una directory, vengono osservati anche su tutti i file che essa contiene.
+La funzione consente di creare un ``\textsl{osservatore}'' (il cosiddetto
+``\textit{watch}'') nella lista di osservazione di una coda di notifica, che
+deve essere indicata specificando il file descriptor ad essa associato
+nell'argomento \param{fd}.\footnote{questo ovviamente dovrà essere un file
+  descriptor creato con \func{inotify\_init}.}  Il file o la directory da
+porre sotto osservazione vengono invece indicati per nome, da passare
+nell'argomento \param{pathname}.  Infine il terzo argomento, \param{mask},
+indica che tipo di eventi devono essere tenuti sotto osservazione e le
+modalità della stessa.  L'operazione può essere ripetuta per tutti i file e le
+directory che si vogliono tenere sotto osservazione,\footnote{anche in questo
+  caso c'è un limite massimo che di default è pari a 8192, ed anche questo
+  valore può essere cambiato con \func{sysctl} o usando il file
+  \procfile{/proc/sys/fs/inotify/max\_user\_watches}.} e si utilizzerà sempre
+un solo file descriptor.
+
+Il tipo di evento che si vuole osservare deve essere specificato
+nell'argomento \param{mask} come maschera binaria, combinando i valori delle
+costanti riportate in tab.~\ref{tab:inotify_event_watch} che identificano i
+singoli bit della maschera ed il relativo significato. In essa si sono marcati
+con un ``$\bullet$'' gli eventi che, quando specificati per una directory,
+vengono osservati anche su tutti i file che essa contiene.  Nella seconda
+parte della tabella si sono poi indicate alcune combinazioni predefinite dei
+flag della prima parte.
 
 \begin{table}[htb]
   \centering
 
 \begin{table}[htb]
   \centering
@@ -1328,49 +1366,122 @@ per una directory, vengono osservati anche su tutti i file che essa contiene.
     \textbf{Valore}  & & \textbf{Significato} \\
     \hline
     \hline
     \textbf{Valore}  & & \textbf{Significato} \\
     \hline
     \hline
-    \const{IN\_ACCESS}        &$\bullet$& c'è stato accesso al file in
+    \const{IN\_ACCESS}        &$\bullet$& C'è stato accesso al file in
                                           lettura.\\  
                                           lettura.\\  
-    \const{IN\_ATTRIB}        &$\bullet$& ci sono stati cambiamenti sui dati
-                                          dell'inode.\\ 
-    \const{IN\_CLOSE\_WRITE}  &$\bullet$& è stato chiuso un file aperto in
+    \const{IN\_ATTRIB}        &$\bullet$& Ci sono stati cambiamenti sui dati
+                                          dell'inode (o sugli attributi
+                                          estesi, vedi
+                                          sez.~\ref{sec:file_xattr}).\\ 
+    \const{IN\_CLOSE\_WRITE}  &$\bullet$& È stato chiuso un file aperto in
                                           scrittura.\\  
                                           scrittura.\\  
-    \const{IN\_CLOSE\_NOWRITE}&$\bullet$& è stato chiuso un file aperto in
-                                          sola lettura.\\ 
-    \const{IN\_CREATE}        &$\bullet$& è stato creato un file o una
+    \const{IN\_CLOSE\_NOWRITE}&$\bullet$& È stato chiuso un file aperto in
+                                          sola lettura.\\
+    \const{IN\_CREATE}        &$\bullet$& È stato creato un file o una
                                           directory in una directory sotto
                                           osservazione.\\  
                                           directory in una directory sotto
                                           osservazione.\\  
-    \const{IN\_DELETE}        &$\bullet$& è stato cancellato un file o una
+    \const{IN\_DELETE}        &$\bullet$& È stato cancellato un file o una
                                           directory in una directory sotto
                                           osservazione.\\ 
                                           directory in una directory sotto
                                           osservazione.\\ 
-    \const{IN\_DELETE\_SELF}  &       &   è stato cancellato il file (o la
+    \const{IN\_DELETE\_SELF}  & --      & È stato cancellato il file (o la
                                           directory) sotto osservazione.\\ 
                                           directory) sotto osservazione.\\ 
-    \const{IN\_MODIFY}        &$\bullet$& è stato modificato il file.\\ 
-    \const{IN\_MOVE\_SELF}    &         & è stato rinominato il file (o la
+    \const{IN\_MODIFY}        &$\bullet$& È stato modificato il file.\\ 
+    \const{IN\_MOVE\_SELF}    &         & È stato rinominato il file (o la
                                           directory) sotto osservazione.\\ 
                                           directory) sotto osservazione.\\ 
-    \const{IN\_MOVED\_FROM}   &$\bullet$& un file è stato spostato fuori dalla
+    \const{IN\_MOVED\_FROM}   &$\bullet$& Un file è stato spostato fuori dalla
                                           directory sotto osservazione.\\ 
                                           directory sotto osservazione.\\ 
-    \const{IN\_MOVED\_TO}     &$\bullet$& un file è stato spostato nella
+    \const{IN\_MOVED\_TO}     &$\bullet$& Un file è stato spostato nella
                                           directory sotto osservazione.\\ 
                                           directory sotto osservazione.\\ 
-    \const{IN\_OPEN}          &$\bullet$& un file è stato aperto.\\ 
+    \const{IN\_OPEN}          &$\bullet$& Un file è stato aperto.\\ 
+    \hline    
+    \const{IN\_CLOSE}         &         & Combinazione di
+                                          \const{IN\_CLOSE\_WRITE} e
+                                          \const{IN\_CLOSE\_NOWRITE}.\\  
+    \const{IN\_MOVE}          &         & Combinazione di
+                                          \const{IN\_MOVED\_FROM} e
+                                          \const{IN\_MOVED\_TO}.\\
+    \const{IN\_ALL\_EVENTS}   &         & Combinazione di tutti i flag
+                                          possibili.\\
     \hline    
   \end{tabular}
     \hline    
   \end{tabular}
-  \caption{Le costanti che identificano i valori per la maschera binaria
-    dell'argomento \param{mask} di \func{inotify\_add\_watch}.} 
+  \caption{Le costanti che identificano i bit della maschera binaria
+    dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano il
+    tipo di evento da tenere sotto osservazione.} 
   \label{tab:inotify_event_watch}
 \end{table}
 
   \label{tab:inotify_event_watch}
 \end{table}
 
-Se non esiste nessun \textit{watch} per il file (o la directory) specificata
+Oltre ai flag di tab.~\ref{tab:inotify_event_watch}, che indicano il tipo di
+evento da osservare e che vengono utilizzati anche in uscita per indicare il
+tipo di evento avvenuto, \func{inotify\_add\_watch} supporta ulteriori
+flag,\footnote{i flag \const{IN\_DONT\_FOLLOW}, \const{IN\_MASK\_ADD} e
+  \const{IN\_ONLYDIR} sono stati introdotti a partire dalle glibc 2.5, se si
+  usa la versione 2.4 è necessario definirli a mano.}  riportati in
+tab.~\ref{tab:inotify_add_watch_flag}, che indicano le modalità di
+osservazione (da passare sempre nell'argomento \param{mask}) e che al
+contrario dei precedenti non vengono mai impostati nei risultati in uscita.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IN\_DONT\_FOLLOW}& Non dereferenzia \param{pathname} se questo è un
+                              link simbolico.\\
+    \const{IN\_MASK\_ADD}   & Aggiunge a quelli già impostati i flag indicati
+                              nell'argomento \param{mask}, invece di
+                              sovrascriverli.\\
+    \const{IN\_ONESHOT}     & Esegue l'osservazione su \param{pathname} per una
+                              sola volta, rimuovendolo poi dalla \textit{watch
+                                list}.\\ 
+    \const{IN\_ONLYDIR}     & Se \param{pathname} è una directory riporta
+                              soltanto gli eventi ad essa relativi e non
+                              quelli per i file che contiene.\\ 
+    \hline    
+  \end{tabular}
+  \caption{Le costanti che identificano i bit della maschera binaria
+    dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano le
+    modalità di osservazione.} 
+  \label{tab:inotify_add_watch_flag}
+\end{table}
+
+Se non esiste nessun \textit{watch} per il file o la directory specificata
 questo verrà creato per gli eventi specificati dall'argomento \param{mask},
 questo verrà creato per gli eventi specificati dall'argomento \param{mask},
-altrimenti la funzione sovrascriverà le impostazioni precedenti. In caso di
-successo la funzione ritorna un intero positivo, detto \textit{watch
-  descriptor} che identifica univocamente l'evento di osservazione. Questo
-valore è importante perché è soltanto con esso che si può rimuovere un evento
-di osservazione, usando la seconda funzione dell'interfaccia di gestione,
-\funcd{inotify\_rm\_watch}, il cui prototipo è:
+altrimenti la funzione sovrascriverà le impostazioni precedenti, a meno che
+non si sia usato il flag \const{IN\_MASK\_ADD}, nel qual caso gli eventi
+specificati saranno aggiunti a quelli già presenti.
+
+Come accennato quando si tiene sotto osservazione una directory vengono
+restituite le informazioni sia riguardo alla directory stessa che ai file che
+essa contiene; questo comportamento può essere disabilitato utilizzando il
+flag \const{IN\_ONLYDIR}, che richiede di riportare soltanto gli eventi
+relativi alla directory stessa. Si tenga presente inoltre che quando si
+osserva una directory vengono riportati solo gli eventi sui file che essa
+contiene direttamente, non quelli relativi a file contenuti in eventuali
+sottodirectory; se si vogliono osservare anche questi sarà necessario creare
+ulteriori \textit{watch} per ciascuna sottodirectory.
+
+Infine usando il flag \const{IN\_ONESHOT} è possibile richiedere una notifica
+singola;\footnote{questa funzionalità però è disponibile soltanto a partire dal
+  kernel 2.6.16.} una volta verificatosi uno qualunque fra gli eventi
+richiesti con \func{inotify\_add\_watch} l'\textsl{osservatore} verrà
+automaticamente rimosso dalla lista di osservazione e nessun ulteriore evento
+sarà più notificato.
+
+In caso di successo \func{inotify\_add\_watch} ritorna un intero positivo,
+detto \textit{watch descriptor}, che identifica univocamente un
+\textsl{osservatore} su una coda di notifica; esso viene usato per farvi
+riferimento sia riguardo i risultati restituiti da \textit{inotify}, che per
+la eventuale rimozione dello stesso. 
+
+La seconda funzione per la gestione delle code di notifica, che permette di
+rimuovere un \textsl{osservatore}, è \funcd{inotify\_rm\_watch}, ed il suo
+prototipo è:
 \begin{prototype}{sys/inotify.h}
   {int inotify\_rm\_watch(int fd, uint32\_t wd)}
 
 \begin{prototype}{sys/inotify.h}
   {int inotify\_rm\_watch(int fd, uint32\_t wd)}
 
-  Rimuove un evento di osservazione.
+  Rimuove un \textsl{osservatore} da una coda di notifica.
   
   \bodydesc{La funzione restituisce 0 in caso di successo, o $-1$ in caso di
     errore, nel qual caso \var{errno} assumerà uno dei valori:
   
   \bodydesc{La funzione restituisce 0 in caso di successo, o $-1$ in caso di
     errore, nel qual caso \var{errno} assumerà uno dei valori:
@@ -1383,10 +1494,26 @@ di osservazione, usando la seconda funzione dell'interfaccia di gestione,
 }
 \end{prototype}
 
 }
 \end{prototype}
 
-Oltre che per la rimozione, il \textit{watch descriptor} viene usato anche per
-identificare l'evento a cui si fa riferimento nella lista dei risultati
-restituiti da \textit{inotify}
-
+La funzione rimuove dalla coda di notifica identificata dall'argomento
+\param{fd} l'osservatore identificato dal \textit{watch descriptor}
+\param{wd};\footnote{ovviamente deve essere usato per questo argomento un
+  valore ritornato da \func{inotify\_add\_watch}, altrimenti si avrà un errore
+  di \errval{EINVAL}.} in caso di successo della rimozione, contemporaneamente
+alla cancellazione dell'osservatore, sulla coda di notifica verrà generato un
+evento di tipo \const{IN\_IGNORED} (vedi
+tab.~\ref{tab:inotify_read_event_flag}). Si tenga presente che se un file
+viene cancellato o un filesystem viene smontato i relativi osservatori vengono
+rimossi automaticamente e non è necessario utilizzare
+\func{inotify\_rm\_watch}.
+
+Come accennato l'interfaccia di \textit{inotify} prevede che gli eventi siano
+notificati come dati presenti in lettura sul file descriptor associato alla
+coda di notifica. Una applicazione pertanto dovrà leggere i dati da detto file
+con una \func{read}, che ritornerà sul buffer i dati presenti nella forma di
+una o più strutture di tipo \struct{inotify\_event} (la cui definizione è
+riportata in fig.~\ref{fig:inotify_event}). Qualora non siano presenti dati la
+\func{read} si bloccherà (a meno di non aver impostato il file descriptor in
+modalità non bloccante) fino all'arrivo di almeno un evento.
 
 \begin{figure}[!htb]
   \footnotesize \centering
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1394,33 +1521,219 @@ restituiti da \textit{inotify}
     \includestruct{listati/inotify_event.h}
   \end{minipage} 
   \normalsize 
     \includestruct{listati/inotify_event.h}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \structd{inotify\_event}.}
+  \caption{La struttura \structd{inotify\_event} usata dall'interfaccia di
+    \textit{inotify} per riportare gli eventi.}
   \label{fig:inotify_event}
 \end{figure}
 
   \label{fig:inotify_event}
 \end{figure}
 
+Una ulteriore caratteristica dell'interfaccia di \textit{inotify} è che essa
+permette di ottenere con \func{ioctl}, come per i file descriptor associati ai
+socket (si veda sez.~\ref{sec:sock_ioctl_IP}) il numero di byte disponibili in
+lettura sul file descriptor, utilizzando su di esso l'operazione
+\const{FIONREAD}.\footnote{questa è una delle operazioni speciali per i file
+  (vedi sez.~\ref{sec:file_ioctl}), che è disponibile solo per i socket e per
+  i file descriptor creati con \func{inotify\_init}.} Si può così utilizzare
+questa operazione, oltre che per predisporre una operazione di lettura con un
+buffer di dimensioni adeguate, anche per ottenere rapidamente il numero di
+file che sono cambiati.
+
+Una volta effettuata la lettura con \func{read} a ciascun evento sarà
+associata una struttura \struct{inotify\_event} contenente i rispettivi dati.
+Per identificare a quale file o directory l'evento corrisponde viene
+restituito nel campo \var{wd} il \textit{watch descriptor} con cui il relativo
+osservatore è stato registrato. Il campo \var{mask} contiene invece una
+maschera di bit che identifica il tipo di evento verificatosi; in essa
+compariranno sia i bit elencati nella prima parte di
+tab.~\ref{tab:inotify_event_watch}, che gli eventuali valori
+aggiuntivi\footnote{questi compaiono solo nel campo \var{mask} di
+  \struct{inotify\_event}, e  non utilizzabili in fase di registrazione
+  dell'osservatore.} di tab.~\ref{tab:inotify_read_event_flag}.
 
 
-Inoltre l'interfaccia di \textit{inotify} permette di conoscere, come avviene
-per i file descriptor associati ai socket (si veda al proposito quanto
-trattato in sez.~\ref{sec:sock_ioctl_IP}) il numero di byte disponibili in
-lettura sul nostro file descriptor, utilizzando su di esso l'operazione
-\const{FIONREAD} con \func{ioctl}.\footnote{questa è una delle operazioni
-  speciali (che abbiamo visto in sez.~\ref{sec:file_ioctl}) che nel caso è
-  disponibile solo per i socket e per i file descriptor creati con
-  \func{inotify\_init}.} Questo consente anche di ottenere rapidamente il
-numero di file che sono cambiati.
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IN\_IGNORED}    & L'osservatore è stato rimosso, sia in maniera 
+                             esplicita con l'uso di \func{inotify\_rm\_watch}, 
+                             che in maniera implicita per la rimozione 
+                             dell'oggetto osservato o per lo smontaggio del
+                             filesystem su cui questo si trova.\\
+    \const{IN\_ISDIR}      & L'evento avvenuto fa riferimento ad una directory
+                             (consente così di distinguere, quando si pone
+                             sotto osservazione una directory, fra gli eventi
+                             relativi ad essa e quelli relativi ai file che
+                             essa contiene).\\
+    \const{IN\_Q\_OVERFLOW}& Si sono eccedute le dimensioni della coda degli
+                             eventi (\textit{overflow} della coda); in questo
+                             caso il valore di \var{wd} è $-1$.\footnotemark\\
+    \const{IN\_UNMOUNT}    & Il filesystem contenente l'oggetto posto sotto
+                             osservazione è stato smontato.\\
+    \hline    
+  \end{tabular}
+  \caption{Le costanti che identificano i bit aggiuntivi usati nella maschera
+    binaria del campo \var{mask} di \struct{inotify\_event}.} 
+  \label{tab:inotify_read_event_flag}
+\end{table}
 
 
+\footnotetext{la coda di notifica ha una dimensione massima specificata dal
+  parametro di sistema \procfile{/proc/sys/fs/inotify/max\_queued\_events} che
+  indica il numero massimo di eventi che possono essere mantenuti sulla
+  stessa; quando detto valore viene ecceduto gli ulteriori eventi vengono
+  scartati, ma viene comunque generato un evento di tipo
+  \const{IN\_Q\_OVERFLOW}.}
+
+Il campo \var{cookie} contiene invece un intero univoco che permette di
+identificare eventi correlati (per i quali avrà lo stesso valore), al momento
+viene utilizzato soltanto per rilevare lo spostamento di un file, consentendo
+così all'applicazione di collegare la corrispondente coppia di eventi
+\const{IN\_MOVED\_TO} e \const{IN\_MOVED\_FROM}.
+
+Infine due campi \var{name} e \var{len} sono utilizzati soltanto quando
+l'evento è relativo ad un file presente in una directory posta sotto
+osservazione, in tal caso essi contengono rispettivamente il nome del file
+(come pathname relativo alla directory osservata) e la relativa dimensione in
+byte. Il campo \var{name} viene sempre restituito come stringa terminata da
+NUL, con uno o più zeri di terminazione, a seconda di eventuali necessità di
+allineamento del risultato, ed il valore di \var{len} corrisponde al totale
+della dimensione di \var{name}, zeri aggiuntivi compresi. La stringa con il
+nome del file viene restituita nella lettura subito dopo la struttura
+\struct{inotify\_event}; questo significa che le dimensioni di ciascun evento
+di \textit{inotify} saranno pari a \code{sizeof(\struct{inotify\_event}) +
+  len}.
+
+Vediamo allora un esempio dell'uso dell'interfaccia di \textit{inotify} con un
+semplice programma che permette di mettere sotto osservazione uno o più file e
+directory. Il programma si chiama \texttt{inotify\_monitor.c} ed il codice
+completo è disponibile coi sorgenti allegati alla guida, il corpo principale
+del programma, che non contiene la sezione di gestione delle opzioni e le
+funzioni di ausilio è riportato in fig.~\ref{fig:inotify_monitor_example}.
+
+\begin{figure}[!htbp]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/inotify_monitor.c}
+  \end{minipage}
+  \normalsize
+  \caption{Esempio di codice che usa l'interfaccia di \textit{inotify}.}
+  \label{fig:inotify_monitor_example}
+\end{figure}
 
 
+Una volta completata la scansione delle opzioni il corpo principale del
+programma inizia controllando (\texttt{\small 11--15}) che sia rimasto almeno
+un argomento che indichi quale file o directory mettere sotto osservazione (e
+qualora questo non avvenga esce stampando la pagina di aiuto); dopo di che
+passa (\texttt{\small 16--20}) all'inizializzazione di \textit{inotify}
+ottenendo con \func{inotify\_init} il relativo file descriptor (oppure usce in
+caso di errore).
+
+Il passo successivo è aggiungere (\texttt{\small 21--30}) alla coda di
+notifica gli opportuni osservatori per ciascuno dei file o directory indicati
+all'invocazione del comando; questo viene fatto eseguendo un ciclo
+(\texttt{\small 22--29}) fintanto che la variabile \var{i}, inizializzata a
+zero (\texttt{\small 21}) all'inizio del ciclo, è minore del numero totale di
+argomenti rimasti. All'interno del ciclo si invoca (\texttt{\small 23})
+\func{inotify\_add\_watch} per ciascuno degli argomenti, usando la maschera
+degli eventi data dalla variabile \var{mask} (il cui valore viene impostato
+nella scansione delle opzioni), in caso di errore si esce dal programma
+altrimenti si incrementa l'indice (\texttt{\small 29}).
+
+Completa l'inizializzazione di \textit{inotify} inizia il ciclo principale
+(\texttt{\small 32--56}) del programma, nel quale si resta in attesa degli
+eventi che si intendono osservare. Questo viene fatto eseguendo all'inizio del
+ciclo (\texttt{\small 33}) una \func{read} che si bloccherà fintanto che non
+si saranno verificati eventi. 
+
+Dato che l'interfaccia di \textit{inotify} può riportare anche più eventi in
+una sola lettura, si è avuto cura di passare alla \func{read} un buffer di
+dimensioni adeguate, inizializzato in (\texttt{\small 7}) ad un valore di
+approssimativamente 512 eventi.\footnote{si ricordi che la quantità di dati
+  restituita da \textit{inotify} è variabile a causa della diversa lunghezza
+  del nome del file restituito insieme a \struct{inotify\_event}.} In caso di
+errore di lettura (\texttt{\small 35--40}) il programma esce con un messaggio
+di errore (\texttt{\small 37--39}), a meno che non si tratti di una
+interruzione della system call, nel qual caso (\texttt{\small 36}) si ripete la
+lettura.
+
+Se la lettura è andata a buon fine invece si esegue un ciclo (\texttt{\small
+  43--52}) per leggere tutti gli eventi restituiti, al solito si inizializza
+l'indice \var{i} a zero (\texttt{\small 42}) e si ripetono le operazioni
+(\texttt{\small 43}) fintanto che esso non supera il numero di byte restituiti
+in lettura. Per ciascun evento all'interno del ciclo si assegna\footnote{si
+  noti come si sia eseguito un opportuno \textit{casting} del puntatore.} alla
+variabile \var{event} l'indirizzo nel buffer della corrispondente struttura
+\struct{inotify\_event} (\texttt{\small 44}), e poi si stampano il numero di
+\textit{watch descriptor} (\texttt{\small 45}) ed il file a cui questo fa
+riferimento (\texttt{\small 46}), ricavato dagli argomenti passati a riga di
+comando sfruttando il fatto che i \textit{watch descriptor} vengono assegnati
+in ordine progressivo crescente a partire da 1.
+
+Qualora sia presente il riferimento ad un nome di file associato all'evento lo
+si stampa (\texttt{\small 47--49}); si noti come in questo caso si sia
+utilizzato il valore del campo \var{event->len} e non al fatto che
+\var{event->name} riporti o meno un puntatore nullo.\footnote{l'interfaccia
+  infatti, qualora il nome non sia presente, non avvalora il campo
+  \var{event->name}, che si troverà a contenere quello che era precedentemente
+  presente nella rispettiva locazione di memoria, nel caso più comune il
+  puntatore al nome di un file osservato in precedenza.} Si utilizza poi
+(\texttt{\small 50}) la funzione \code{printevent}, che interpreta il valore
+del campo \var{event->mask} per stampare il tipo di eventi
+accaduti.\footnote{per il relativo codice, che non riportiamo in quanto non
+  essenziale alla comprensione dell'esempio, si possono utilizzare direttamente
+  i sorgenti allegati alla guida.} Infine (\texttt{\small 51}) si provvede ad
+aggiornare l'indice \var{i} per farlo puntare all'evento successivo.
+
+Se adesso usiamo il programma per mettere sotto osservazione una directory, e
+da un altro terminale eseguiamo il comando \texttt{ls} otterremo qualcosa del
+tipo di:
+\begin{verbatim}
+piccardi@gethen:~/gapil/sources$ ./inotify_monitor -a /home/piccardi/gapil/
+Watch descriptor 1
+Observed event on /home/piccardi/gapil/
+IN_OPEN, 
+Watch descriptor 1
+Observed event on /home/piccardi/gapil/
+IN_CLOSE_NOWRITE, 
+\end{verbatim}
 
 
-% TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
-% TODO e man inotify
+I lettori più accorti si saranno resi conto che nel ciclo di lettura degli
+eventi appena illustrato non viene trattato il caso particolare in cui la
+funzione \func{read} restituisce in \var{nread} un valore nullo. Lo si è fatto
+perché con \textit{inotify} il ritorno di una \func{read} con un valore nullo
+avviene soltanto, come forma di avviso, quando si sia eseguita la funzione
+specificando un buffer di dimensione insufficiente a contenere anche un solo
+evento. Nel nostro caso le dimensioni erano senz'altro sufficienti, per cui
+tale evenienza non si verificherà mai.
+
+Ci si potrà però chiedere cosa succede se il buffer è sufficiente per un
+evento, ma non per tutti gli eventi verificatisi. Come si potrà notare nel
+codice illustrato in precedenza non si è presa nessuna precauzione per
+verificare che non ci fossero stati troncamenti dei dati. Anche in questo caso
+il comportamento scelto è corretto, perché l'interfaccia di \textit{inotify}
+garantisce automaticamente, anche quando ne sono presenti in numero maggiore,
+di restituire soltanto il numero di eventi che possono rientrare completamente
+nelle dimensioni del buffer specificato.\footnote{si avrà cioè, facendo
+  riferimento sempre al codice di fig.~\ref{fig:inotify_monitor_example}, che
+  \var{read} sarà in genere minore delle dimensioni di \var{buffer} ed uguale
+  soltanto qualora gli eventi corrispondano esattamente alle dimensioni di
+  quest'ultimo.} Se gli eventi sono di più saranno restituiti solo quelli che
+entrano interamente nel buffer e gli altri saranno restituiti alla successiva
+chiamata di \func{read}.
+
+Infine un'ultima caratteristica dell'interfaccia di \textit{inotify} è che gli
+eventi restituiti nella lettura formano una sequenza ordinata, è cioè
+garantito che se si esegue uno spostamento di un file gli eventi vengano
+generati nella sequenza corretta. L'interfaccia garantisce anche che se si
+verificano più eventi consecutivi identici (vale a dire con gli stessi valori
+dei campi \var{wd}, \var{mask}, \var{cookie}, e \var{name}) questi vengono
+raggruppati in un solo evento.
 
 \index{file!inotify|)}
 
 
 
 \index{file!inotify|)}
 
 
-% TODO inserire anche eventfd (vedi http://lwn.net/Articles/233462/)
-
-
-
 \subsection{L'interfaccia POSIX per l'I/O asincrono}
 \label{sec:file_asyncronous_io}
 
 \subsection{L'interfaccia POSIX per l'I/O asincrono}
 \label{sec:file_asyncronous_io}
 
@@ -1541,11 +1854,11 @@ appena descritta; i rispettivi prototipi sono:
   \bodydesc{Le funzioni restituiscono 0 in caso di successo, e -1 in caso di
     errore, nel qual caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
   \bodydesc{Le funzioni restituiscono 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}] 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
+  \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}.
     \var{aio\_offset} o \var{aio\_reqprio} di \param{aiocbp}.
-  \item[\errcode{EAGAIN}] La coda delle richieste è momentaneamente piena.
+  \item[\errcode{EAGAIN}] la coda delle richieste è momentaneamente piena.
   \end{errlist}
 }
 \end{functions}
   \end{errlist}
 }
 \end{functions}
@@ -1712,10 +2025,10 @@ specifica operazione; il suo prototipo 
     completate, e -1 in caso di errore nel qual caso \var{errno} assumerà uno
     dei valori:
     \begin{errlist}
     completate, e -1 in caso di errore nel qual caso \var{errno} assumerà uno
     dei valori:
     \begin{errlist}
-    \item[\errcode{EAGAIN}] Nessuna operazione è stata completata entro
+    \item[\errcode{EAGAIN}] nessuna operazione è stata completata entro
       \param{timeout}.
       \param{timeout}.
-    \item[\errcode{ENOSYS}] La funzione non è implementata.
-    \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+    \item[\errcode{ENOSYS}] la funzione non è implementata.
+    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
     \end{errlist}
   }
 \end{prototype}
     \end{errlist}
   }
 \end{prototype}
@@ -1743,13 +2056,13 @@ lettura o scrittura; il suo prototipo 
   \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}
   \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{EAGAIN}] Nessuna operazione è stata completata entro
+    \item[\errcode{EAGAIN}] nessuna operazione è stata completata entro
       \param{timeout}.
       \param{timeout}.
-    \item[\errcode{EINVAL}] Si è passato un valore di \param{mode} non valido
+    \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}.
       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.
+    \item[\errcode{ENOSYS}] la funzione non è implementata.
+    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
     \end{errlist}
   }
 \end{prototype}
     \end{errlist}
   }
 \end{prototype}
@@ -1785,79 +2098,8 @@ Oltre alle precedenti modalit
   asincrono}, esistono altre funzioni che implementano delle modalità di
 accesso ai file più evolute rispetto alle normali funzioni di lettura e
 scrittura che abbiamo esaminato in sez.~\ref{sec:file_base_func}. In questa
   asincrono}, esistono altre funzioni che implementano delle modalità di
 accesso ai file più evolute rispetto alle normali funzioni di lettura e
 scrittura che abbiamo esaminato in sez.~\ref{sec:file_base_func}. In questa
-sezione allora prenderemo in esame le interfacce per l'\textsl{I/O
-  vettorizzato} e per l'\textsl{I/O mappato in memoria} e la funzione
-\func{sendfile}.
-
-
-\subsection{I/O vettorizzato}
-\label{sec:file_multiple_io}
-
-Un caso abbastanza comune è quello in cui ci si trova a dover eseguire una
-serie multipla di operazioni di I/O, come una serie di letture o scritture di
-vari buffer. Un esempio tipico è quando i dati sono strutturati nei campi di
-una struttura ed essi devono essere caricati o salvati su un file.  Benché
-l'operazione sia facilmente eseguibile attraverso una serie multipla di
-chiamate, ci sono casi in cui si vuole poter contare sulla atomicità delle
-operazioni.
-
-Per questo motivo BSD 4.2\footnote{Le due funzioni sono riprese da BSD4.4 ed
-  integrate anche dallo standard Unix 98. Fino alle libc5, Linux usava
-  \type{size\_t} come tipo dell'argomento \param{count}, una scelta logica,
-  che però è stata dismessa per restare aderenti allo standard.} ha introdotto
-due nuove system call, \funcd{readv} e \funcd{writev}, che permettono di
-effettuare con una sola chiamata una lettura o una scrittura su una serie di
-buffer (quello che viene chiamato \textsl{I/O vettorizzato}. I relativi
-prototipi sono:
-\begin{functions}
-  \headdecl{sys/uio.h}
-  
-  \funcdecl{int readv(int fd, const struct iovec *vector, int count)} 
-  \funcdecl{int writev(int fd, const struct iovec *vector, int count)} 
-
-  Eseguono rispettivamente una lettura o una scrittura vettorizzata.
-  
-  \bodydesc{Le funzioni restituiscono il numero di byte letti o scritti in
-    caso di successo, e -1 in caso di errore, nel qual caso \var{errno}
-    assumerà uno dei valori:
-  \begin{errlist}
-  \item[\errcode{EINVAL}] si è specificato un valore non valido per uno degli
-    argomenti (ad esempio \param{count} è maggiore di \const{MAX\_IOVEC}).
-  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima di
-    di avere eseguito una qualunque lettura o scrittura.
-  \item[\errcode{EAGAIN}] \param{fd} è stato aperto in modalità non bloccante e
-  non ci sono dati in lettura.
-  \item[\errcode{EOPNOTSUPP}] la coda delle richieste è momentaneamente piena.
-  \end{errlist}
-  ed anche \errval{EISDIR}, \errval{EBADF}, \errval{ENOMEM}, \errval{EFAULT}
-  (se non sono stati allocati correttamente i buffer specificati nei campi
-  \var{iov\_base}), più gli eventuali errori delle funzioni di lettura e
-  scrittura eseguite su \param{fd}.}
-\end{functions}
-
-Entrambe le funzioni usano una struttura \struct{iovec}, la cui definizione è
-riportata in fig.~\ref{fig:file_iovec}, che definisce dove i dati devono
-essere letti o scritti ed in che quantità. Il primo campo della struttura,
-\var{iov\_base}, contiene l'indirizzo del buffer ed il secondo,
-\var{iov\_len}, la dimensione dello stesso.
-
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includestruct{listati/iovec.h}
-  \end{minipage} 
-  \normalsize 
-  \caption{La struttura \structd{iovec}, usata dalle operazioni di I/O
-    vettorizzato.} 
-  \label{fig:file_iovec}
-\end{figure}
-
-La lista dei buffer da utilizzare viene indicata attraverso l'argomento
-\param{vector} che è un vettore di strutture \struct{iovec}, la cui lunghezza
-è specificata dall'argomento \param{count}.  Ciascuna struttura dovrà essere
-inizializzata opportunamente per indicare i vari buffer da e verso i quali
-verrà eseguito il trasferimento dei dati. Essi verranno letti (o scritti)
-nell'ordine in cui li si sono specificati nel vettore \param{vector}.
+sezione allora prenderemo in esame le interfacce per l'\textsl{I/O mappato in
+  memoria}, per l'\textsl{I/O vettorizzato} e altre funzioni di I/O avanzato.
 
 
 \subsection{File mappati in memoria}
 
 
 \subsection{File mappati in memoria}
@@ -1873,7 +2115,7 @@ file in una sezione dello spazio di indirizzi del processo.
  che lo ha allocato
 \begin{figure}[htb]
   \centering
  che lo ha allocato
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=10cm]{img/mmap_layout}
+  \includegraphics[width=12cm]{img/mmap_layout}
   \caption{Disposizione della memoria di un processo quando si esegue la
   mappatura in memoria di un file.}
   \label{fig:file_mmap_layout}
   \caption{Disposizione della memoria di un processo quando si esegue la
   mappatura in memoria di un file.}
   \label{fig:file_mmap_layout}
@@ -1930,29 +2172,29 @@ eseguire la mappatura in memoria di un file, 
     in caso di successo, e \const{MAP\_FAILED} (-1) in caso di errore, nel
     qual caso \var{errno} assumerà uno dei valori:
     \begin{errlist}
     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
+    \item[\errcode{EBADF}] il file descriptor non è valido, e non si è usato
       \const{MAP\_ANONYMOUS}.
     \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}.
       \const{MAP\_ANONYMOUS}.
     \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
+    \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).
       \param{offset} non sono validi (o troppo grandi o non allineati sulla
       dimensione delle pagine).
-    \item[\errcode{ETXTBSY}] Si è impostato \const{MAP\_DENYWRITE} ma
+    \item[\errcode{ETXTBSY}] si è impostato \const{MAP\_DENYWRITE} ma
       \param{fd} è aperto in scrittura.
       \param{fd} è aperto in scrittura.
-    \item[\errcode{EAGAIN}] Il file è bloccato, o si è bloccata troppa memoria
+    \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}).
       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
+    \item[\errcode{ENOMEM}] non c'è memoria o si è superato il limite sul
       numero di mappature possibili.
       numero di mappature possibili.
-    \item[\errcode{ENODEV}] Il filesystem di \param{fd} non supporta il memory
+    \item[\errcode{ENODEV}] il filesystem di \param{fd} non supporta il memory
       mapping.
       mapping.
-    \item[\errcode{EPERM}] L'argomento \param{prot} ha richiesto
+    \item[\errcode{EPERM}] l'argomento \param{prot} ha richiesto
       \const{PROT\_EXEC}, ma il filesystem di \param{fd} è montato con
       l'opzione \texttt{noexec}.
       \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
+    \item[\errcode{ENFILE}] si è superato il limite del sistema sul numero di
       file aperti (vedi sez.~\ref{sec:sys_resource_limit}).
     \end{errlist}
   }
       file aperti (vedi sez.~\ref{sec:sys_resource_limit}).
     \end{errlist}
   }
@@ -1983,7 +2225,6 @@ multiplo della dimensione di una pagina di memoria.
   \label{tab:file_mmap_prot}
 \end{table}
 
   \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
 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
@@ -1993,7 +2234,7 @@ Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux
   che si chiama una \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
   che si chiama una \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_flag}; il valore specificato deve essere
+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.
 
 L'argomento \param{flags} specifica infine qual è il tipo di oggetto mappato,
 compatibile con la modalità di accesso con cui si è aperto il file.
 
 L'argomento \param{flags} specifica infine qual è il tipo di oggetto mappato,
@@ -2015,7 +2256,7 @@ tab.~\ref{tab:file_mmap_flag}.
                              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
                              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. \\
+                             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
     \const{MAP\_SHARED}    & I cambiamenti sulla memoria mappata vengono
                              riportati sul file e saranno immediatamente
                              visibili agli altri processi che mappano lo stesso
@@ -2023,7 +2264,7 @@ tab.~\ref{tab:file_mmap_flag}.
                              aggiornato fino alla chiamata di \func{msync} o
                              \func{munmap}), e solo allora le modifiche saranno
                              visibili per l'I/O convenzionale. Incompatibile
                              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}. \\ 
+                             con \const{MAP\_PRIVATE}.\\ 
     \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
     \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
@@ -2033,13 +2274,13 @@ tab.~\ref{tab:file_mmap_flag}.
                              salvate su swap in caso di necessità. Non è
                              specificato se i cambiamenti sul file originale
                              vengano riportati sulla regione
                              salvate su swap in caso di necessità. Non è
                              specificato se i cambiamenti sul file originale
                              vengano riportati sulla regione
-                             mappata. Incompatibile con \const{MAP\_SHARED}. \\
+                             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\_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\_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}
     \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}
@@ -2047,7 +2288,7 @@ tab.~\ref{tab:file_mmap_flag}.
                              modifiche fatte alla regione mappata, in
                              questo caso dopo una scrittura, se non c'è più
                              memoria disponibile, si ha l'emissione di
                              modifiche fatte alla regione mappata, in
                              questo caso dopo una scrittura, se non c'è più
                              memoria disponibile, si ha l'emissione di
-                             un \const{SIGSEGV}. \\
+                             un \const{SIGSEGV}.\\
     \const{MAP\_LOCKED}    & Se impostato impedisce lo swapping delle pagine
                              mappate.\\
     \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} stack. Indica 
     \const{MAP\_LOCKED}    & Se impostato impedisce lo swapping delle pagine
                              mappate.\\
     \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} stack. Indica 
@@ -2065,9 +2306,9 @@ tab.~\ref{tab:file_mmap_flag}.
                              richiesto \const{MAP\_FIXED}.\\
     \const{MAP\_POPULATE}  & Esegue il \itindex{prefaulting}
                              \textit{prefaulting} delle pagine di memoria
                              richiesto \const{MAP\_FIXED}.\\
     \const{MAP\_POPULATE}  & Esegue il \itindex{prefaulting}
                              \textit{prefaulting} delle pagine di memoria
-                             necessarie alla mappatura. \\
+                             necessarie alla mappatura.\\
     \const{MAP\_NONBLOCK}  & Esegue un \textit{prefaulting} più limitato che
     \const{MAP\_NONBLOCK}  & Esegue un \textit{prefaulting} più limitato che
-                             non causa I/O.\footnotemark \\
+                             non causa I/O.\footnotemark\\
 %     \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
 %                              mappata con \func{mremap}, proposto ma pare non
 %                              implementato.\\
 %     \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
 %                              mappata con \func{mremap}, proposto ma pare non
 %                              implementato.\\
@@ -2096,10 +2337,10 @@ eseguita su un segmento di dimensioni rigorosamente multiple di quelle di una
 pagina, ed in generale queste potranno non corrispondere alle dimensioni
 effettive del file o della sezione che si vuole mappare.
 
 pagina, ed in generale queste potranno non corrispondere alle dimensioni
 effettive del file o della sezione che si vuole mappare.
 
-\footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di
+\footnotetext[68]{dato che tutti faranno riferimento alle stesse pagine di
   memoria.}  
 
   memoria.}  
 
-\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è stato
+\footnotetext[69]{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}.}
   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}.}
@@ -2110,7 +2351,7 @@ effettive del file o della sezione che si vuole mappare.
 
 \begin{figure}[!htb] 
   \centering
 
 \begin{figure}[!htb] 
   \centering
-  \includegraphics[width=12cm]{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}
   \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}
@@ -2153,7 +2394,7 @@ che sono utilizzabili solo con questa interfaccia.
 
 \begin{figure}[htb]
   \centering
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=12cm]{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}
   \caption{Schema della mappatura in memoria di file di dimensioni inferiori
     alla lunghezza richiesta.}
   \label{fig:file_mmap_exceed}
@@ -2210,10 +2451,10 @@ memoria mappata con il file su disco; il suo prototipo 
   \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}
   \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{EINVAL}] O \param{start} non è multiplo di
+    \item[\errcode{EINVAL}] o \param{start} non è multiplo di
       \const{PAGE\_SIZE}, o si è specificato un valore non valido per
       \param{flags}.
       \const{PAGE\_SIZE}, o si è specificato un valore non valido per
       \param{flags}.
-    \item[\errcode{EFAULT}] L'intervallo specificato non ricade in una zona
+    \item[\errcode{EFAULT}] l'intervallo specificato non ricade in una zona
       precedentemente mappata.
     \end{errlist}
   }
       precedentemente mappata.
     \end{errlist}
   }
@@ -2240,7 +2481,8 @@ del file aggiornato.
                             siano invalidate.\\
     \hline    
   \end{tabular}
                             siano invalidate.\\
     \hline    
   \end{tabular}
-  \caption{Valori dell'argomento \param{flag} di \func{msync}.}
+  \caption{Le costanti che identificano i bit per la maschera binaria
+    dell'argomento \param{flag} di \func{msync}.}
   \label{tab:file_mmap_rsync}
 \end{table}
 
   \label{tab:file_mmap_rsync}
 \end{table}
 
@@ -2267,7 +2509,7 @@ mappatura della memoria usando la funzione \funcd{munmap}, il suo prototipo 
   \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}
   \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{EINVAL}] L'intervallo specificato non ricade in una zona
+    \item[\errcode{EINVAL}] l'intervallo specificato non ricade in una zona
       precedentemente mappata.
     \end{errlist}
   }
       precedentemente mappata.
     \end{errlist}
   }
@@ -2421,10 +2663,10 @@ nuova system call, \funcd{remap\_file\_pages}, il cui prototipo 
   
   Permette di rimappare non linearmente un precedente \textit{memory mapping}.
 
   
   Permette di rimappare non linearmente un precedente \textit{memory mapping}.
 
-  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+  \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}
     errore, nel qual caso \var{errno} assumerà uno dei valori:
     \begin{errlist}
-    \item[\errcode{EINVAL}] Si è usato un valore non valido per uno degli
+    \item[\errcode{EINVAL}] si è usato un valore non valido per uno degli
       argomenti o \param{start} non fa riferimento ad un \textit{memory
         mapping} valido creato con \const{MAP\_SHARED}.
     \end{errlist}
       argomenti o \param{start} non fa riferimento ad un \textit{memory
         mapping} valido creato con \const{MAP\_SHARED}.
     \end{errlist}
@@ -2483,37 +2725,844 @@ mappatura che gi
 
 \itindend{memory~mapping}
 
 
 \itindend{memory~mapping}
 
+\subsection{I/O vettorizzato: \func{readv} e \func{writev}}
+\label{sec:file_multiple_io}
 
 
-%\subsection{L'I/O diretto fra file descriptor}
-%\label{sec:file_sendfile_splice}
+Un caso abbastanza comune è quello in cui ci si trova a dover eseguire una
+serie multipla di operazioni di I/O, come una serie di letture o scritture di
+vari buffer. Un esempio tipico è quando i dati sono strutturati nei campi di
+una struttura ed essi devono essere caricati o salvati su un file.  Benché
+l'operazione sia facilmente eseguibile attraverso una serie multipla di
+chiamate, ci sono casi in cui si vuole poter contare sulla atomicità delle
+operazioni.
 
 
+Per questo motivo su BSD 4.2 sono state introdotte due nuove system call,
+\funcd{readv} e \funcd{writev},\footnote{in Linux le due funzioni sono riprese
+  da BSD4.4, esse sono previste anche dallo standard POSIX.1-2001.}  che
+permettono di effettuare con una sola chiamata una lettura o una scrittura su
+una serie di buffer (quello che viene chiamato \textsl{I/O vettorizzato}. I
+relativi prototipi sono:
+\begin{functions}
+  \headdecl{sys/uio.h}
+  
+  \funcdecl{int readv(int fd, const struct iovec *vector, int count)} 
+  \funcdecl{int writev(int fd, const struct iovec *vector, int count)} 
 
 
-%Uno dei problemi 
+  Eseguono rispettivamente una lettura o una scrittura vettorizzata.
+  
+  \bodydesc{Le funzioni restituiscono il numero di byte letti o scritti in
+    caso di successo, e -1 in caso di errore, nel qual caso \var{errno}
+    assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EINVAL}] si è specificato un valore non valido per uno degli
+    argomenti (ad esempio \param{count} è maggiore di \const{IOV\_MAX}).
+  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima di
+    di avere eseguito una qualunque lettura o scrittura.
+  \item[\errcode{EAGAIN}] \param{fd} è stato aperto in modalità non bloccante e
+    non ci sono dati in lettura.
+  \item[\errcode{EOPNOTSUPP}] la coda delle richieste è momentaneamente piena.
+  \end{errlist}
+  ed anche \errval{EISDIR}, \errval{EBADF}, \errval{ENOMEM}, \errval{EFAULT}
+  (se non sono stati allocati correttamente i buffer specificati nei campi
+  \var{iov\_base}), più gli eventuali errori delle funzioni di lettura e
+  scrittura eseguite su \param{fd}.}
+\end{functions}
 
 
-%NdA è da finire, sul perché non è abilitata fra file vedi:
+Entrambe le funzioni usano una struttura \struct{iovec}, la cui definizione è
+riportata in fig.~\ref{fig:file_iovec}, che definisce dove i dati devono
+essere letti o scritti ed in che quantità. Il primo campo della struttura,
+\var{iov\_base}, contiene l'indirizzo del buffer ed il secondo,
+\var{iov\_len}, la dimensione dello stesso.
 
 
-%\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}}
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/iovec.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{iovec}, usata dalle operazioni di I/O
+    vettorizzato.} 
+  \label{fig:file_iovec}
+\end{figure}
 
 
+La lista dei buffer da utilizzare viene indicata attraverso l'argomento
+\param{vector} che è un vettore di strutture \struct{iovec}, la cui lunghezza
+è specificata dall'argomento \param{count}.\footnote{fino alle libc5, Linux
+  usava \type{size\_t} come tipo dell'argomento \param{count}, una scelta
+  logica, che però è stata dismessa per restare aderenti allo standard
+  POSIX.1-2001.}  Ciascuna struttura dovrà essere inizializzata opportunamente
+per indicare i vari buffer da e verso i quali verrà eseguito il trasferimento
+dei dati. Essi verranno letti (o scritti) nell'ordine in cui li si sono
+specificati nel vettore \param{vector}.
+
+La standardizzazione delle due funzioni all'interno della revisione
+POSIX.1-2001 prevede anche che sia possibile avere un limite al numero di
+elementi del vettore \param{vector}. Qualora questo sussista, esso deve essere
+indicato dal valore dalla costante \const{IOV\_MAX}, definita come le altre
+costanti analoghe (vedi sez.~\ref{sec:sys_limits}) in \file{limits.h}; lo
+stesso valore deve essere ottenibile in esecuzione tramite la funzione
+\func{sysconf} richiedendo l'argomento \const{\_SC\_IOV\_MAX} (vedi
+sez.~\ref{sec:sys_sysconf}).
+
+Nel caso di Linux il limite di sistema è di 1024, però se si usano le
+\acr{glibc} queste forniscono un \textit{wrapper} per le system call che si
+accorge se una operazione supererà il precedente limite, in tal caso i dati
+verranno letti o scritti con le usuali \func{read} e \func{write} usando un
+buffer di dimensioni sufficienti appositamente allocato e sufficiente a
+contenere tutti i dati indicati da \param{vector}. L'operazione avrà successo
+ma si perderà l'atomicità del trasferimento da e verso la destinazione finale.
+
+% TODO verificare cosa succederà a preadv e pwritev o alla nuova niovec
+% vedi http://lwn.net/Articles/164887/
+
+
+\subsection{L'I/O diretto fra file descriptor: \func{sendfile} e \func{splice}}
+\label{sec:file_sendfile_splice}
+
+Uno dei problemi che si presentano nella gestione dell'I/O è quello in cui si
+devono trasferire grandi quantità di dati da un file descriptor ed un altro;
+questo usualmente comporta la lettura dei dati dal primo file descriptor in un
+buffer in memoria, da cui essi vengono poi scritti sul secondo.
+
+Benché il kernel ottimizzi la gestione di questo processo quando si ha a che
+fare con file normali, in generale quando i dati da trasferire sono molti si
+pone il problema di effettuare trasferimenti di grandi quantità di dati da
+kernel space a user space e all'indietro, quando in realtà potrebbe essere più
+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
+  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 è:
+\begin{functions}  
+  \headdecl{sys/sendfile.h} 
 
 
-% TODO documentare la funzione sendfile
-% 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)
+  \funcdecl{ssize\_t sendfile(int out\_fd, int in\_fd, off\_t *offset, size\_t
+    count)} 
+  
+  Copia dei dati da un file descriptor ad un altro.
 
 
+  \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{EAGAIN}] si è impostata la modalità non bloccante su
+      \param{out\_fd} e la scrittura si bloccherebbe.
+    \item[\errcode{EINVAL}] i file descriptor non sono validi, o sono bloccati
+      (vedi sez.~\ref{sec:file_locking}), o \func{mmap} non è disponibile per
+      \param{in\_fd}.
+    \item[\errcode{EIO}] si è avuto un errore di lettura da \param{in\_fd}.
+    \item[\errcode{ENOMEM}] non c'è memoria sufficiente per la lettura da
+      \param{in\_fd}.
+    \end{errlist}
+    ed inoltre \errcode{EBADF} e \errcode{EFAULT}.
+  }
+\end{functions}
 
 
+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
+\func{write} questo valore può essere inferiore a quanto richiesto con
+\param{count}.
+
+Se il puntatore \param{offset} è nullo la funzione legge i dati a partire
+dalla posizione corrente su \param{in\_fd}, altrimenti verrà usata la
+posizione indicata dal valore puntato da \param{offset}; in questo caso detto
+valore sarà aggiornato, come \textit{value result argument}, per indicare la
+posizione del byte successivo all'ultimo che è stato letto, mentre la
+posizione corrente sul file non sarà modificata. Se invece \param{offset} è
+nullo la posizione corrente sul file sarà aggiornata tenendo conto dei byte
+letti da \param{in\_fd}.
+
+Fino ai kernel della serie 2.4 la funzione è utilizzabile su un qualunque file
+descriptor, e permette di sostituire la invocazione successiva di una
+\func{read} e una \func{write} (e l'allocazione del relativo buffer) con una
+sola chiamata a \funcd{sendfile}. In questo modo si può diminuire il numero di
+chiamate al sistema e risparmiare in trasferimenti di dati da kernel space a
+user space e viceversa.  La massima utilità della funzione si ha comunque per
+il trasferimento di dati da un file su disco ad un socket di
+rete,\footnote{questo è il caso classico del lavoro eseguito da un server web,
+  ed infatti Apache ha una opzione per il supporto esplicito di questa
+  funzione.} dato che in questo caso diventa possibile effettuare il
+trasferimento diretto via DMA dal controller del disco alla scheda di rete,
+senza neanche allocare un buffer nel kernel,\footnote{il meccanismo è detto
+  \textit{zerocopy} in quanto i dati non vengono mai copiati dal kernel, che
+  si limita a programmare solo le operazioni di lettura e scrittura via DMA.}
+ottenendo la massima efficienza possibile senza pesare neanche sul processore.
+
+In seguito però ci si è accorti che, fatta eccezione per il trasferimento
+diretto da file a socket, non sempre \func{sendfile} comportava miglioramenti
+significativi delle prestazioni rispetto all'uso in sequenza di \func{read} e
+\func{write},\footnote{nel caso generico infatti il kernel deve comunque
+  allocare un buffer ed effettuare la copia dei dati, e in tal caso spesso il
+  guadagno ottenibile nel ridurre il numero di chiamate al sistema non
+  compensa le ottimizzazioni che possono essere fatte da una applicazione in
+  user space che ha una conoscenza diretta su come questi sono strutturati.} e
+che anzi in certi casi si potevano avere anche dei peggioramenti.  Questo ha
+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}
+  {\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
+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
+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
+  senso che un trasferimento di dati fra due file con \func{sendfile} non
+  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;\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
+  scopi da \func{sendfile}, quello che rende \func{splice} davvero diversa è
+  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}
+  {\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}
+e \func{tee}, che tratteremo più avanti) è appunto l'uso di un buffer in
+kernel space, e questo è anche quello che ne ha semplificato l'adozione,
+perché l'infrastruttura per la gestione di un tale buffer è presente fin dagli
+albori di Unix per la realizzazione delle \textit{pipe} (vedi
+sez.~\ref{sec:ipc_unix}). Dal punto di vista concettuale allora \func{splice}
+non è altro che una diversa interfaccia (rispetto alle \textit{pipe}) con cui
+utilizzare in user space l'oggetto ``\textsl{buffer in kernel space}''.
+
+Così se per una \textit{pipe} o una \textit{fifo} il buffer viene utilizzato
+come area di memoria (vedi fig.~\ref{fig:ipc_pipe_singular}) dove appoggiare i
+dati che vengono trasferiti da un capo all'altro della stessa per creare un
+meccanismo di comunicazione fra processi, nel caso di \func{splice} il buffer
+viene usato o come fonte dei dati che saranno scritti su un file, o come
+destinazione dei dati che vengono letti da un file. La funzione \funcd{splice}
+fornisce quindi una interfaccia generica che consente di trasferire dati da un
+buffer ad un file o viceversa; il suo prototipo, accessibile solo dopo aver
+definito la macro \macro{\_GNU\_SOURCE},\footnote{si ricordi che questa
+  funzione non è contemplata da nessuno standard, è presente solo su Linux, e
+  pertanto deve essere evitata se si vogliono scrivere programmi portabili.}
+è il seguente:
+\begin{functions}  
+  \headdecl{fcntl.h} 
 
 
+  \funcdecl{long splice(int fd\_in, off\_t *off\_in, int fd\_out, off\_t
+    *off\_out, size\_t len, unsigned int flags)}
+  
+  Trasferisce dati da un file verso una pipe o viceversa.
 
 
-%\subsection{Gestione avanzata del caching dei dati}
-%\label{sec:file_fadvise}
+  \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}] uno o entrambi fra \param{fd\_in} e \param{fd\_out}
+      non sono file descriptor validi o, rispettivamente, non sono stati
+      aperti in lettura o scrittura.
+    \item[\errcode{EINVAL}] il filesystem su cui si opera non supporta
+      \func{splice}, oppure nessuno dei file descriptor è una pipe, oppure si
+      è dato un valore a \param{off\_in} o \param{off\_out} ma il
+      corrispondente file è un dispositivo che non supporta la funzione
+      \func{seek}.
+    \item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'operazione
+      richiesta.
+    \item[\errcode{ESPIPE}] o \param{off\_in} o \param{off\_out} non sono
+      \const{NULL} ma il corrispondente file descriptor è una \textit{pipe}.
+    \end{errlist}
+  }
+\end{functions}
+
+La funzione esegue un trasferimento di \param{len} byte dal file descriptor
+\param{fd\_in} al file descriptor \param{fd\_out}, uno dei quali deve essere
+una \textit{pipe}; l'altro file descriptor può essere
+qualunque.\footnote{questo significa che può essere, oltre che un file di
+  dati, anche un altra \textit{pipe}, o un socket.}  Come accennato una
+\textit{pipe} non è altro che un buffer in kernel space, per cui a seconda che
+essa sia usata per \param{fd\_in} o \param{fd\_out} si avrà rispettivamente la
+copia dei dati dal buffer al file o viceversa. 
+
+In caso di successo la funzione ritorna il numero di byte trasferiti, che può
+essere, come per le normali funzioni di lettura e scrittura su file, inferiore
+a quelli richiesti; un valore negativo indicherà un errore mentre un valore
+nullo indicherà che non ci sono dati da trasferire (ad esempio si è giunti
+alla fine del file in lettura). Si tenga presente che, a seconda del verso del
+trasferimento dei dati, la funzione si comporta nei confronti del file
+descriptor che fa riferimento al file ordinario, come \func{read} o
+\func{write}, e pertanto potrà anche bloccarsi (a meno che non si sia aperto
+il suddetto file in modalità non bloccante).
+
+I due argomenti \param{off\_in} e \param{off\_out} consentono di specificare,
+come per l'analogo \param{offset} di \func{sendfile}, la posizione all'interno
+del file da cui partire per il trasferimento dei dati. Come per
+\func{sendfile} un valore nullo indica di usare la posizione corrente sul
+file, ed essa sarà aggiornata automaticamente secondo il numero di byte
+trasferiti. Un valore non nullo invece deve essere un puntatore ad una
+variabile intera che indica la posizione da usare; questa verrà aggiornata, al
+ritorno della funzione, al byte successivo all'ultimo byte trasferito.
+Ovviamente soltanto uno di questi due argomenti, e più precisamente quello che
+fa riferimento al file descriptor non associato alla \textit{pipe}, può essere
+specificato come valore non nullo.
+
+Infine l'argomento \param{flags} consente di controllare alcune
+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{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}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{SPLICE\_F\_MOVE}    & Suggerisce al kernel di spostare le pagine
+                                 di memoria contenenti i dati invece di
+                                 copiarle;\footnotemark viene usato soltanto
+                                 da \func{splice}.\\ 
+    \const{SPLICE\_F\_NONBLOCK}& Richiede di operare in modalità non
+                                 bloccante; questo flag influisce solo sulle
+                                 operazioni che riguardano l'I/O da e verso la
+                                 \textit{pipe}. Nel caso di \func{splice}
+                                 questo significa che la funzione potrà
+                                 comunque bloccarsi nell'accesso agli altri
+                                 file descriptor (a meno che anch'essi non
+                                 siano stati aperti in modalità non
+                                 bloccante).\\
+    \const{SPLICE\_F\_MORE}    & Indica al kernel che ci sarà l'invio di
+                                 ulteriori dati in una \func{splice}
+                                 successiva, questo è un suggerimento utile
+                                 che viene usato quando \param{fd\_out} è un
+                                 socket.\footnotemark Attualmente viene usato
+                                 solo da \func{splice}, potrà essere
+                                 implementato in futuro anche per
+                                 \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
+                                 usa \const{SPLICE\_F\_MOVE} potrà spostare le 
+                                 pagine con successo, altrimenti esse dovranno
+                                 essere copiate; per usare questa opzione i
+                                 dati dovranno essere opportunamente allineati
+                                 in posizione ed in dimensione alle pagine di
+                                 memoria. Viene usato soltanto da
+                                 \func{vmsplice}.\\
+    \hline
+  \end{tabular}
+  \caption{Le costanti che identificano i bit della maschera binaria
+    dell'argomento \param{flags} di \func{splice}, \func{vmsplice} e
+    \func{tee}.} 
+  \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{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
+  memoria.}
+
+Per capire meglio il funzionamento di \func{splice} vediamo un esempio con un
+semplice programma che usa questa funzione per effettuare la copia di un file
+su un altro senza utilizzare buffer in user space. Il programma si chiama
+\texttt{splicecp.c} ed il codice completo è disponibile coi sorgenti allegati
+alla guida, il corpo principale del programma, che non contiene la sezione di
+gestione delle opzioni e le funzioni di ausilio è riportato in
+fig.~\ref{fig:splice_example}.
+
+Lo scopo del programma è quello di eseguire la copia dei con \func{splice},
+questo significa che si dovrà usare la funzione due volte, prima per leggere i
+dati e poi per scriverli, appoggiandosi ad un buffer in kernel space (vale a
+dire ad una \textit{pipe}); lo schema del flusso dei dati è illustrato in
+fig.~\ref{fig:splicecp_data_flux}. 
+
+\begin{figure}[htb]
+  \centering
+  \includegraphics[height=6cm]{img/splice_copy}
+  \caption{Struttura del flusso di dati usato dal programma \texttt{splicecp}.}
+  \label{fig:splicecp_data_flux}
+\end{figure}
+
+Una volta trattate le opzioni il programma verifica che restino
+(\texttt{\small 13--16}) i due argomenti che indicano il file sorgente ed il
+file destinazione. Il passo successivo è aprire il file sorgente
+(\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}[!phtb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/splicecp.c}
+  \end{minipage}
+  \normalsize
+  \caption{Esempio di codice che usa \func{splice} per effettuare la copia di
+    un file.}
+  \label{fig:splice_example}
+\end{figure}
+
+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} 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
+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--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 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 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 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}
 
 
-% TODO documentare \func{madvise}
-% TODO documentare \func{mincore}
+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.
+
+\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/}
+  {\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.
+
+
+
+\subsection{Gestione avanzata dell'accesso ai dati dei file}
+\label{sec:file_fadvise}
+
+Nell'uso generico dell'interfaccia per l'accesso al contenuto dei file le
+operazioni di lettura e scrittura non necessitano di nessun intervento di
+supervisione da parte dei programmi, si eseguirà una \func{read} o una
+\func{write}, i dati verranno passati al kernel che provvederà ad effettuare
+tutte le operazioni (e a gestire il \textit{caching} dei dati) per portarle a
+termine in quello che ritiene essere il modo più efficiente.
+
+Il problema è che il concetto di migliore efficienza impiegato dal kernel è
+relativo all'uso generico, mentre esistono molti casi in cui ci sono esigenze
+specifiche dei singoli programmi, che avendo una conoscenza diretta di come
+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 e controllare la gestione del relativo
+\textit{caching}.
+
+Una prima funzione che può essere utilizzata per modificare la gestione
+ordinaria dell'I/O su un 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 cache, così
+che le seguenti operazioni di lettura non debbano subire il ritardo dovuto
+all'accesso al disco; il suo prototipo è:
+\begin{functions}
+  \headdecl{fcntl.h}
+
+  \funcdecl{ssize\_t readahead(int fd, off64\_t *offset, size\_t count)}
+  
+  Esegue una lettura preventiva del contenuto di un file in cache.
+
+  \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 venga letto in anticipo il contenuto del file
+\param{fd} a partire dalla posizione \param{offset} e per un ammontare di
+\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
+\param{offset} e \param{count} arrotondati di conseguenza.
+
+La funzione estende quello che è un comportamento normale del
+kernel\footnote{per ottimizzare gli accessi al disco il kernel quando si legge
+  un file, aspettandosi che l'accesso prosegua, esegue sempre una lettura
+  anticipata di una certa quantità di dati; questo meccanismo viene chiamato
+  \textit{readahead}, da cui deriva il nome della funzione.} effettuando la
+lettura in cache della sezione richiesta e 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
+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.
+
+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).
+    \item[\errcode{ESPIPE}] previsto dallo standard se \param{fd} è una pipe o
+      un socket (ma su Linux viene restituito \errcode{EINVAL}).
+    \end{errlist}
+  }
+\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
+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 utilizza 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}& L'applicazione si aspetta di accedere di
+                                   accedere ai dati specificati in maniera
+                                   sequenziale, a partire dalle posizioni più
+                                   basse.\\ 
+    \const{POSIX\_FADV\_RANDOM}  & I dati saranno letti in maniera
+                                   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.\\ 
+    \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}
+
+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, 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}
+danno invece 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 sempre soddisfatta (ed un valore superiore è
+solo raramente di qualche utilità). In particolare l'uso di
+\const{POSIX\_FADV\_WILLNEED} si può considerare l'equivalente POSIX di
+\func{readahead}.
+
+Infine con \const{POSIX\_FADV\_DONTNEED} si dice al kernel di liberare le
+pagine di cache occupate dai dati presenti nella regione di file indicata.
+Questa è una indicazione utile che permette di alleggerire il carico sulla
+cache, ed un programma può utilizzare periodicamente questa funzione per
+liberare pagine di memoria da dati che non sono più utilizzati per far posto a
+nuovi dati utili.\footnote{la pagina di manuale riporta l'esempio dello
+  streaming di file di grosse dimensioni, dove le pagine occupate dai dati già
+  inviati possono essere tranquillamente scartate.}
+
+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, è:
+\begin{functions}  
+  \headdecl{fcntl.h} 
+
+  \funcdecl{int posix\_fallocate(int fd, off\_t offset, off\_t len)}
+  
+  Richiede la allocazione di spazio disco per un file.
+
+  \bodydesc{La funzione restituisce 0 in caso di successo e direttamente un
+    codice di errore, in caso di fallimento, in questo caso \var{errno} non
+    viene impostata, ma sarà restituito direttamente uno dei valori:
+    \begin{errlist}
+    \item[\errcode{EBADF}] l'argomento \param{fd} non è un file descriptor
+      valido o non è aperto in scrittura.
+    \item[\errcode{EINVAL}] o \param{offset} o \param{len} sono minori di
+      zero.
+    \item[\errcode{EFBIG}] il valore di (\param{offset} + \param{len}) eccede
+      la dimensione massima consentita per un file.
+    \item[\errcode{ENODEV}] l'argomento \param{fd} non fa riferimento ad un
+      file regolare.
+    \item[\errcode{ENOSPC}] non c'è sufficiente spazio disco per eseguire
+      l'operazione. 
+    \item[\errcode{ESPIPE}] l'argomento \param{fd} è una pipe.
+  \end{errlist}
+  }
+\end{functions}
+
+La funzione si 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 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{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
+
 %\subsection{L'utilizzo delle porte di I/O}
 %\label{sec:file_io_port}
 %
 %\subsection{L'utilizzo delle porte di I/O}
 %\label{sec:file_io_port}
 %
@@ -2523,6 +3572,7 @@ mappatura che gi
 
 
 
 
 
 
+
 \section{Il file locking}
 \label{sec:file_locking}
 
 \section{Il file locking}
 \label{sec:file_locking}
 
@@ -2543,7 +3593,7 @@ in cui diversi processi scrivono, mescolando in maniera imprevedibile il loro
 output sul file.
 
 In tutti questi casi il \textit{file locking} è la tecnica che permette di
 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.
 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.
@@ -2654,7 +3704,7 @@ rimuovere un \textit{file lock} 
   \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}
   \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{EWOULDBLOCK}] Il file ha già un blocco attivo, e si è
+    \item[\errcode{EWOULDBLOCK}] il file ha già un blocco attivo, e si è
       specificato \const{LOCK\_NB}.
     \end{errlist}
   }
       specificato \const{LOCK\_NB}.
     \end{errlist}
   }
@@ -2790,17 +3840,17 @@ essa viene usata solo secondo il prototipo:
   \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}
   \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{EACCES}] L'operazione è proibita per la presenza di
+    \item[\errcode{EACCES}] l'operazione è proibita per la presenza di
       \textit{file lock} da parte di altri processi.
       \textit{file lock} da parte di altri processi.
-    \item[\errcode{ENOLCK}] Il sistema non ha le risorse per il locking: ci
+    \item[\errcode{ENOLCK}] il sistema non ha le risorse per il locking: ci
       sono troppi segmenti di lock aperti, si è esaurita la tabella dei lock,
       o il protocollo per il locking remoto è fallito.
       sono troppi segmenti di lock aperti, si è esaurita la tabella dei lock,
       o il protocollo per il locking remoto è fallito.
-    \item[\errcode{EDEADLK}] Si è richiesto un lock su una regione bloccata da
+    \item[\errcode{EDEADLK}] si è richiesto un lock su una regione bloccata da
       un altro processo che è a sua volta in attesa dello sblocco di un lock
       mantenuto dal processo corrente; si avrebbe pertanto un
       \itindex{deadlock} \textit{deadlock}. Non è garantito che il sistema
       riconosca sempre questa situazione.
       un altro processo che è a sua volta in attesa dello sblocco di un lock
       mantenuto dal processo corrente; si avrebbe pertanto un
       \itindex{deadlock} \textit{deadlock}. Non è garantito che il sistema
       riconosca sempre questa situazione.
-    \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale prima
+    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
       di poter acquisire un lock.
     \end{errlist}
     ed inoltre \errval{EBADF}, \errval{EFAULT}.
       di poter acquisire un lock.
     \end{errlist}
     ed inoltre \errval{EBADF}, \errval{EFAULT}.
@@ -2937,13 +3987,6 @@ ed impedirle restituendo un errore di \errcode{EDEADLK} alla funzione che
 cerca di acquisire un lock che porterebbe ad un \itindex{deadlock}
 \textit{deadlock}.
 
 cerca di acquisire un lock che porterebbe ad un \itindex{deadlock}
 \textit{deadlock}.
 
-\begin{figure}[!bht]
-  \centering \includegraphics[width=13cm]{img/file_posix_lock}
-  \caption{Schema dell'architettura del file locking, nel caso particolare  
-    del suo utilizzo secondo l'interfaccia standard POSIX.}
-  \label{fig:file_posix_lock}
-\end{figure}
-
 
 Per capire meglio il funzionamento del file locking in semantica POSIX (che
 differisce alquanto rispetto da quello di BSD, visto
 
 Per capire meglio il funzionamento del file locking in semantica POSIX (che
 differisce alquanto rispetto da quello di BSD, visto
@@ -2962,6 +4005,13 @@ questo caso la titolarit
 voce nella \itindex{file~table} \textit{file table}, ma con il valore del
 \acr{pid} del processo.
 
 voce nella \itindex{file~table} \textit{file table}, ma con il valore del
 \acr{pid} del processo.
 
+\begin{figure}[!bht]
+  \centering \includegraphics[width=13cm]{img/file_posix_lock}
+  \caption{Schema dell'architettura del file locking, nel caso particolare  
+    del suo utilizzo secondo l'interfaccia standard POSIX.}
+  \label{fig:file_posix_lock}
+\end{figure}
+
 Quando si richiede un lock il kernel effettua una scansione di tutti i lock
 presenti sul file\footnote{scandisce cioè la \itindex{linked~list}
   \textit{linked list} delle strutture \struct{file\_lock}, scartando
 Quando si richiede un lock il kernel effettua una scansione di tutti i lock
 presenti sul file\footnote{scandisce cioè la \itindex{linked~list}
   \textit{linked list} delle strutture \struct{file\_lock}, scartando
@@ -3232,10 +4282,10 @@ che utilizza la funzione \funcd{lockf}, il cui prototipo 
   \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}
   \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{EWOULDBLOCK}] Non è possibile acquisire il lock, e si è
+    \item[\errcode{EWOULDBLOCK}] non è possibile acquisire il lock, e si è
       selezionato \const{LOCK\_NB}, oppure l'operazione è proibita perché il
       file è mappato in memoria.
       selezionato \const{LOCK\_NB}, oppure l'operazione è proibita perché il
       file è mappato in memoria.
-    \item[\errcode{ENOLCK}] Il sistema non ha le risorse per il locking: ci
+    \item[\errcode{ENOLCK}] il sistema non ha le risorse per il locking: ci
       sono troppi segmenti di lock aperti, si è esaurita la tabella dei lock.
     \end{errlist}
     ed inoltre \errval{EBADF}, \errval{EINVAL}.
       sono troppi segmenti di lock aperti, si è esaurita la tabella dei lock.
     \end{errlist}
     ed inoltre \errval{EBADF}, \errval{EINVAL}.
@@ -3257,7 +4307,7 @@ tab.~\ref{tab:file_lockf_type}.
     \const{LOCK\_SH}& Richiede uno \textit{shared lock}. Più processi possono
                       mantenere un lock condiviso sullo stesso file.\\
     \const{LOCK\_EX}& Richiede un \textit{exclusive lock}. Un solo processo
     \const{LOCK\_SH}& Richiede uno \textit{shared lock}. Più processi possono
                       mantenere un lock condiviso sullo stesso file.\\
     \const{LOCK\_EX}& Richiede un \textit{exclusive lock}. Un solo processo
-                      alla volta può mantenere un lock esclusivo su un file. \\
+                      alla volta può mantenere un lock esclusivo su un file.\\
     \const{LOCK\_UN}& Sblocca il file.\\
     \const{LOCK\_NB}& Non blocca la funzione quando il lock non è disponibile,
                       si specifica sempre insieme ad una delle altre operazioni
     \const{LOCK\_UN}& Sblocca il file.\\
     \const{LOCK\_NB}& Non blocca la funzione quando il lock non è disponibile,
                       si specifica sempre insieme ad una delle altre operazioni
@@ -3413,10 +4463,17 @@ possibilit
 % LocalWords:  attribute Universe epoll Solaris kqueue level triggered Jonathan
 % LocalWords:  Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT
 % LocalWords:  MOD wait EPOLLIN EPOLLOUT EPOLLRDHUP SOCK EPOLLPRI EPOLLERR one
 % LocalWords:  attribute Universe epoll Solaris kqueue level triggered Jonathan
 % LocalWords:  Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT
 % LocalWords:  MOD wait EPOLLIN EPOLLOUT EPOLLRDHUP SOCK EPOLLPRI EPOLLERR one
-% LocalWords:  EPOLLHUP EPOLLET EPOLLONESHOT shot maxevents
+% 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 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 posix fadvise TC advice FADV NORMAL
 
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
 
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
+% LocalWords:  SEQUENTIAL NOREUSE WILLNEED DONTNEED streaming fallocate EFBIG