Indicizzati file sotto /proc, ed ulteriore materiale su ''inotify''.
[gapil.git] / fileadv.tex
index 4737913a90046c33e7d9df43791a2242ebbaa9e9..662d8f8afaae9c9f03d0890d4eec82f915cec2f7 100644 (file)
@@ -71,17 +71,18 @@ eseguire in continuazione delle system call che nella gran parte dei casi
 falliranno.
 
 Per superare questo problema è stato introdotto il concetto di \textit{I/O
-  multiplexing}, una nuova modalità di operazioni che consenta di tenere sotto
+  multiplexing}, una nuova modalità di operazioni che consente di tenere sotto
 controllo più file descriptor in contemporanea, permettendo di bloccare un
 processo quando le operazioni volute non sono possibili, e di riprenderne
-l'esecuzione una volta che almeno una di quelle richieste sia disponibile, in
+l'esecuzione una volta che almeno una di quelle richieste sia effettuabile, in
 modo da poterla eseguire con la sicurezza di non restare bloccati.
 
 Dato che, come abbiamo già accennato, per i normali file su disco non si ha
 mai un accesso bloccante, l'uso più comune delle funzioni che esamineremo nei
 prossimi paragrafi è per i server di rete, in cui esse vengono utilizzate per
 tenere sotto controllo dei socket; pertanto ritorneremo su di esse con
-ulteriori dettagli e qualche esempio in sez.~\ref{sec:TCP_sock_multiplexing}.
+ulteriori dettagli e qualche esempio di utilizzo concreto in
+sez.~\ref{sec:TCP_sock_multiplexing}.
 
 
 \subsection{Le funzioni \func{select} e \func{pselect}}
@@ -96,7 +97,7 @@ Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
   \headdecl{sys/time.h}
   \headdecl{sys/types.h}
   \headdecl{unistd.h}
-  \funcdecl{int select(int n, fd\_set *readfds, fd\_set *writefds, fd\_set
+  \funcdecl{int select(int ndfs, fd\_set *readfds, fd\_set *writefds, fd\_set
     *exceptfds, struct timeval *timeout)}
   
   Attende che uno dei file descriptor degli insiemi specificati diventi
@@ -109,8 +110,8 @@ Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
   \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
     degli insiemi.
   \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
-  \item[\errcode{EINVAL}] Si è specificato per \param{n} un valore negativo o
-    un valore non valido per \param{timeout}.
+  \item[\errcode{EINVAL}] Si è specificato per \param{ndfs} un valore negativo
+    un valore non valido per \param{timeout}.
   \end{errlist}
   ed inoltre \errval{ENOMEM}.
 }
@@ -158,7 +159,9 @@ massimo, esso indica le dimensioni massime dei numeri usati nei \textit{file
   1003.1-2001, è definito in \file{sys/select.h}, ed è pari a 1024.} Si tenga
 presente che i \textit{file descriptor set} devono sempre essere inizializzati
 con \macro{FD\_ZERO}; passare a \func{select} un valore non inizializzato può
-dar luogo a comportamenti non prevedibili.
+dar luogo a comportamenti non prevedibili; allo stesso modo usare
+\macro{FD\_SET} o \macro{FD\_CLR} con un file descriptor il cui valore eccede
+\const{FD\_SETSIZE} può dare luogo ad un comportamento indefinito.
 
 La funzione richiede di specificare tre insiemi distinti di file descriptor;
 il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
@@ -170,26 +173,25 @@ effettuare una lettura,\footnote{per essere precisi la funzione ritorner
   accadere che \func{select} riporti il relativo file descriptor come
   leggibile, ma una successiva \func{read} si blocchi.} il secondo,
 \param{writefds}, per verificare la possibilità effettuare una scrittura ed il
-terzo,
-\param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati
+terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati
 urgenti \itindex{out-of-band} su un socket, vedi
 sez.~\ref{sec:TCP_urgent_data}).
 
 Dato che in genere non si tengono mai sotto controllo fino a
 \const{FD\_SETSIZE} file contemporaneamente la funzione richiede di
-specificare qual è il numero massimo dei file descriptor indicati nei tre
+specificare qual è il valore più alto fra i file descriptor indicati nei tre
 insiemi precedenti. Questo viene fatto per efficienza, per evitare di passare
 e far controllare al kernel una quantità di memoria superiore a quella
-necessaria. Questo limite viene indicato tramite l'argomento \param{n}, che
-deve corrispondere al valore massimo aumentato di uno.\footnote{i file
-  descriptor infatti sono contati a partire da zero, ed il valore indica il
-  numero di quelli da tenere sotto controllo; dimenticarsi di aumentare di uno
-  il valore di \param{n} è un errore comune.}  Infine l'argomento
-\param{timeout}, specifica un tempo massimo di attesa prima che la funzione
-ritorni; se impostato a \val{NULL} la funzione attende indefinitamente. Si può
-specificare anche un tempo nullo (cioè una struttura \struct{timeval} con i
-campi impostati a zero), qualora si voglia semplicemente controllare lo stato
-corrente dei file descriptor.
+necessaria. Questo limite viene indicato tramite l'argomento \param{ndfs}, che
+deve corrispondere al valore massimo aumentato di uno.\footnote{si ricordi che
+  i file descriptor sono numerati progressivamente a partire da zero, ed il
+  valore indica il numero più alto fra quelli da tenere sotto controllo;
+  dimenticarsi di aumentare di uno il valore di \param{ndfs} è un errore
+  comune.}  Infine l'argomento \param{timeout} specifica un tempo massimo di
+attesa prima che la funzione ritorni; se impostato a \val{NULL} la funzione
+attende indefinitamente. Si può specificare anche un tempo nullo (cioè una
+struttura \struct{timeval} con i campi impostati a zero), qualora si voglia
+semplicemente controllare lo stato corrente dei file descriptor.
 
 La funzione restituisce il numero di file descriptor pronti,\footnote{questo è
   il comportamento previsto dallo standard, ma la standardizzazione della
@@ -204,6 +206,15 @@ contenuto.
 
 \itindend{file~descriptor~set}
 
+Una volta ritornata la funzione si potrà controllare quali sono i file
+descriptor pronti ed operare su di essi, si tenga presente però che si tratta
+solo di un suggerimento, esistono infatti condizioni\footnote{ad esempio
+  quando su un socket arrivano dei dati che poi vengono scartati perché
+  corrotti.} in cui \func{select} può riportare in maniera spuria che un file
+descriptor è pronto in lettura, quando una successiva lettura si bloccherebbe.
+Per questo quando si usa \textit{I/O multiplexing} è sempre raccomandato l'uso
+delle funzioni di lettura e scrittura in modalità non bloccante.
+
 In Linux \func{select} modifica anche il valore di \param{timeout},
 impostandolo al tempo restante in caso di interruzione prematura; questo è
 utile quando la funzione viene interrotta da un segnale, in tal caso infatti
@@ -218,10 +229,10 @@ rimanente.\footnote{questo pu
 
 Uno dei problemi che si presentano con l'uso di \func{select} è che il suo
 comportamento dipende dal valore del file descriptor che si vuole tenere sotto
-controllo.  Infatti il kernel riceve con \param{n} un valore massimo per tale
-valore, e per capire quali sono i file descriptor da tenere sotto controllo
-dovrà effettuare una scansione su tutto l'intervallo, che può anche essere
-anche molto ampio anche se i file descriptor sono solo poche unità; tutto ciò
+controllo.  Infatti il kernel riceve con \param{ndfs} un limite massimo per
+tale valore, e per capire quali sono i file descriptor da tenere sotto
+controllo dovrà effettuare una scansione su tutto l'intervallo, che può anche
+essere molto ampio anche se i file descriptor sono solo poche unità; tutto ciò
 ha ovviamente delle conseguenze ampiamente negative per le prestazioni.
 
 Inoltre c'è anche il problema che il numero massimo dei file che si possono
@@ -259,8 +270,8 @@ precedenti, ed inoltre aggiunge a \func{select} una nuova funzione
   \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
     degli insiemi.
   \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
-  \item[\errcode{EINVAL}] Si è specificato per \param{n} un valore negativo o
-    un valore non valido per \param{timeout}.
+  \item[\errcode{EINVAL}] Si è specificato per \param{ndfs} un valore negativo
+    un valore non valido per \param{timeout}.
   \end{errlist}
   ed inoltre \errval{ENOMEM}.}
 \end{prototype}
@@ -305,7 +316,7 @@ contestualmente all'esecuzione della funzione,\footnote{in Linux per
   kernel 2.6.16, non era presente la relativa system call, e la funzione era
   implementata nelle \acr{glibc} attraverso \func{select} (vedi \texttt{man
     select\_tut}) per cui la possibilità di \itindex{race~condition}
-  \textit{race condition} permaneva; in tale situzione si può ricorrere ad una
+  \textit{race condition} permaneva; in tale situazione si può ricorrere ad una
   soluzione alternativa, chiamata \itindex{self-pipe trick} \textit{self-pipe
     trick}, che consiste nell'aprire una pipe (vedi sez.~\ref{sec:ipc_pipes})
   ed usare \func{select} sul capo in lettura della stessa; si può indicare
@@ -357,17 +368,6 @@ indica un'attesa indefinita, mentre un valore nullo comporta il ritorno
 immediato (e può essere utilizzato per impiegare \func{poll} in modalità
 \textsl{non-bloccante}).
 
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includestruct{listati/pollfd.h}
-  \end{minipage} 
-  \normalsize 
-  \caption{La struttura \structd{pollfd}, utilizzata per specificare le
-    modalità di controllo di un file descriptor alla funzione \func{poll}.}
-  \label{fig:file_pollfd}
-\end{figure}
-
 Per ciascun file da controllare deve essere inizializzata una struttura
 \struct{pollfd} nel vettore indicato dall'argomento \param{ufds}.  La
 struttura, la cui definizione è riportata in fig.~\ref{fig:file_pollfd},
@@ -381,6 +381,17 @@ tutto indipendenti da quelli in uscita (che vengono restituiti in
 \var{revents}) non è necessario reinizializzare tutte le volte il valore delle
 strutture \struct{pollfd} a meno di non voler cambiare qualche condizione.
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/pollfd.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{pollfd}, utilizzata per specificare le
+    modalità di controllo di un file descriptor alla funzione \func{poll}.}
+  \label{fig:file_pollfd}
+\end{figure}
+
 Le costanti che definiscono i valori relativi ai bit usati nelle maschere
 binarie dei campi \var{events} e \var{revents} sono riportati in
 tab.~\ref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono
@@ -399,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.\\ 
-    \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{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.\\
@@ -444,11 +455,30 @@ valore nullo indica che si 
 indica un errore nella chiamata, il cui codice viene riportato al solito
 tramite \var{errno}.
 
+L'uso di \func{poll} consente di superare alcuni dei problemi illustrati in
+precedenza per \func{select}; anzitutto, dato che in questo caso si usa un
+vettore di strutture \struct{pollfd} di dimensione arbitraria, non esiste il
+limite introdotto dalle dimensioni massime di un \itindex{file~descriptor~set}
+\textit{file descriptor set} e la dimensione dei dati passati al kernel
+dipende solo dal numero dei file descriptor che si vogliono controllare, non
+dal loro valore.\footnote{anche se usando dei bit un \textit{file descriptor
+    set} può essere più efficiente di un vettore di strutture \struct{pollfd},
+  qualora si debba osservare un solo file descriptor con un valore molto alto
+  ci si troverà ad utilizzare inutilmente un maggiore quantitativo di
+  memoria.} 
+
+Inoltre con \func{select} lo stesso \itindex{file~descriptor~set} \textit{file
+  descriptor set} è usato sia in ingresso che in uscita, e questo significa
+che tutte le volte che si vuole ripetere l'operazione occorre reinizializzarlo
+da capo. Questa operazione, che può essere molto onerosa se i file descriptor
+da tenere sotto osservazione sono molti, non è invece necessaria con
+\func{poll}.
+
 Abbiamo visto in sez.~\ref{sec:file_select} come lo standard POSIX preveda una
 variante di \func{select} che consente di gestire correttamente la ricezione
 dei segnali nell'attesa su un file descriptor.  Con l'introduzione di una
 implementazione reale di \func{pselect} nel kernel 2.6.16, è stata aggiunta
-anche una analoga funzione che svolga lo stesso ruolo per \func{poll}. 
+anche una analoga funzione che svolga lo stesso ruolo per \func{poll}.
 
 In questo caso si tratta di una estensione che è specifica di Linux e non è
 prevista da nessuno standard; essa può essere utilizzata esclusivamente se si
@@ -489,13 +519,380 @@ puntatore ad una struttura \struct{timespec}, gli altri argomenti comuni con
 risultati illustrati in precedenza.
 
 
-% TODO accennare a ppoll vedi articolo LWN http://lwn.net/Articles/176750/
+\subsection{L'interfaccia di \textit{epoll}}
+\label{sec:file_epoll}
+
+\itindbeg{epoll}
+
+Nonostante \func{poll} presenti alcuni vantaggi rispetto a \func{select},
+anche questa funzione non è molto efficiente quando deve essere utilizzata con
+un gran numero di file descriptor,\footnote{in casi del genere \func{select}
+  viene scartata a priori, perché può avvenire che il numero di file
+  descriptor ecceda le dimensioni massime di un \itindex{file~descriptor~set}
+  \textit{file descriptor set}.} in particolare nel caso in cui solo pochi di
+questi diventano attivi. Il problema in questo caso è che il tempo impiegato
+da \func{poll} a trasferire i dati da e verso il kernel è proporzionale al
+numero di file descriptor osservati, non a quelli che presentano attività.
+
+Quando ci sono decine di migliaia di file descriptor osservati e migliaia di
+eventi al secondo,\footnote{il caso classico è quello di un server web di un
+  sito con molti accessi.} l'uso di \func{poll} comporta la necessità di
+trasferire avanti ed indietro da user space a kernel space la lunga lista
+delle strutture \struct{pollfd} migliaia di volte al secondo. A questo poi si
+aggiunge il fatto che la maggior parte del tempo di esecuzione sarà impegnato
+ad eseguire una scansione su tutti i file descriptor tenuti sotto controllo
+per determinare quali di essi (in genere una piccola percentuale) sono
+diventati attivi. In una situazione come questa l'uso delle funzioni classiche
+dell'interfaccia dell'\textit{I/O multiplexing} viene a costituire un collo di
+bottiglia che degrada irrimediabilmente le prestazioni.
+
+Per risolvere questo tipo di situazioni sono state ideate delle interfacce
+specialistiche\footnote{come \texttt{/dev/poll} in Solaris, o \texttt{kqueue}
+  in BSD.} il cui scopo fondamentale è quello di restituire solamente le
+informazioni relative ai file descriptor osservati che presentano una
+attività, evitando così le problematiche appena illustrate. In genere queste
+prevedono che si registrino una sola volta i file descriptor da tenere sotto
+osservazione, e forniscono un meccanismo che notifica quali di questi
+presentano attività.
+
+Le modalità con cui avviene la notifica sono due, la prima è quella classica
+(quella usata da \func{poll} e \func{select}) che viene chiamata \textit{level
+  triggered}.\footnote{la nomenclatura è stata introdotta da Jonathan Lemon in
+  un articolo su \texttt{kqueue} al BSDCON 2000, e deriva da quella usata
+  nell'elettronica digitale.} In questa modalità vengono notificati i file
+descriptor che sono \textsl{pronti} per l'operazione richiesta, e questo
+avviene indipendentemente dalle operazioni che possono essere state fatte su
+di essi a partire dalla precedente notifica.  Per chiarire meglio il concetto
+ricorriamo ad un esempio: se su un file descriptor sono diventati disponibili
+in lettura 2000 byte ma dopo la notifica ne sono letti solo 1000 (ed è quindi
+possibile eseguire una ulteriore lettura dei restanti 1000), in modalità
+\textit{level triggered} questo sarà nuovamente notificato come
+\textsl{pronto}.
+
+La seconda modalità, è detta \textit{edge triggered}, e prevede che invece
+vengano notificati solo i file descriptor che hanno subito una transizione da
+\textsl{non pronti} a \textsl{pronti}. Questo significa che in modalità
+\textit{edge triggered} nel caso del precedente esempio il file descriptor
+diventato pronto da cui si sono letti solo 1000 byte non verrà nuovamente
+notificato come pronto, nonostante siano ancora disponibili in lettura 1000
+byte. Solo una volta che si saranno esauriti tutti i byte disponibili, e che
+il file descriptor sia tornato non essere pronto, si potrà ricevere una
+ulteriore notifica qualora ritornasse pronto.
+
+Nel caso di Linux al momento la sola interfaccia che fornisce questo tipo di
+servizio è \textit{epoll},\footnote{l'interfaccia è stata creata da Davide
+  Libenzi, ed è stata introdotta per la prima volta nel kernel 2.5.44, ma la
+  sua forma definitiva è stata raggiunta nel kernel 2.5.66.} anche se sono in
+discussione altre interfacce con le quali si potranno effettuare lo stesso
+tipo di operazioni;\footnote{al momento della stesura di queste note (Giugno
+  2007) un'altra interfaccia proposta è quella di \textit{kevent}, che
+  fornisce un sistema di notifica di eventi generico in grado di fornire le
+  stesse funzionalità di \textit{epoll}, esiste però una forte discussione
+  intorno a tutto ciò e niente di definito.}  \textit{epoll} è in grado di
+operare sia in modalità \textit{level triggered} che \textit{edge triggered}.
+
+La prima versione \textit{epoll} prevedeva l'apertura di uno speciale file di
+dispositivo, \texttt{/dev/epoll}, per ottenere un file descriptor da
+utilizzare con le funzioni dell'interfaccia,\footnote{il backporting
+  dell'interfaccia per il kernel 2.4, non ufficiale, utilizza sempre questo
+  file.} ma poi si è passati all'uso una apposita \textit{system call}.  Il
+primo passo per usare l'interfaccia di \textit{epoll} è pertanto quello di
+chiamare la funzione \funcd{epoll\_create}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+  {int epoll\_create(int size)}
+  
+  Apre un file descriptor per \textit{epoll}.
+  
+  \bodydesc{La funzione restituisce un file descriptor in caso di successo, o
+    $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EINVAL}] si è specificato un valore di \param{size} non
+    positivo.
+  \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
+    nel sistema.
+  \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
+    l'istanza.
+  \end{errlist}
+}
+\end{prototype}
+
+La funzione restituisce un file descriptor speciale,\footnote{esso non è
+  associato a nessun file su disco, inoltre a differenza dei normali file
+  descriptor non può essere inviato ad un altro processo attraverso un socket
+  locale (vedi sez.~\ref{sec:sock_fd_passing}).} detto anche \textit{epoll
+  descriptor}, che viene associato alla infrastruttura utilizzata dal kernel
+per gestire la notifica degli eventi; l'argomento \param{size} serve a dare
+l'indicazione del numero di file descriptor che si vorranno tenere sotto
+controllo, ma costituisce solo un suggerimento per semplificare l'allocazione
+di risorse sufficienti, non un valore massimo.
+
+Una volta ottenuto un file descriptor per \textit{epoll} il passo successivo è
+indicare quali file descriptor mettere sotto osservazione e quali operazioni
+controllare, per questo si deve usare la seconda funzione dell'interfaccia,
+\funcd{epoll\_ctl}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+  {int epoll\_ctl(int epfd, int op, int fd, struct epoll\_event *event)}
+  
+  Esegue le operazioni di controllo di \textit{epoll}.
+  
+  \bodydesc{La funzione restituisce $0$ in caso di successo o $-1$ in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] il file descriptor \param{epfd} o \param{fd} non sono
+    validi.
+  \item[\errcode{EEXIST}] l'operazione richiesta è \const{EPOLL\_CTL\_ADD} ma
+    \param{fd} è già stato inserito in \param{epfd}.
+  \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+    con \func{epoll\_create}, o \param{fd} è lo stesso \param{epfd} o
+    l'operazione richiesta con \param{op} non è supportata.
+  \item[\errcode{ENOENT}] l'operazione richiesta è \const{EPOLL\_CTL\_MOD} o
+    \const{EPOLL\_CTL\_DEL} ma \param{fd} non è inserito in \param{epfd}.
+  \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel gestire
+    l'operazione richiesta.
+  \item[\errcode{EPERM}] il file \param{fd} non supporta \textit{epoll}.
+  \end{errlist}
+}
+\end{prototype}
+
+Il comportamento della funzione viene controllato dal valore dall'argomento
+\param{op} che consente di specificare quale operazione deve essere eseguita.
+Le costanti che definiscono i valori utilizzabili per \param{op}
+sono riportate in tab.~\ref{tab:epoll_ctl_operation}, assieme al significato
+delle operazioni cui fanno riferimento.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \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.\\
+    \const{EPOLL\_CTL\_MOD}& Modifica le modalità di osservazione del file
+                             descriptor \param{fd} secondo il contenuto di
+                             \param{event}.\\
+    \const{EPOLL\_CTL\_DEL}& Rimuove il file descriptor \param{fd} dalla lista
+                             dei file controllati tramite \param{epfd}.\\
+    \hline    
+  \end{tabular}
+  \caption{Valori dell'argomento \param{op} che consentono di scegliere quale
+    operazione di controllo effettuare con la funzione \func{epoll\_ctl}.} 
+  \label{tab:epoll_ctl_operation}
+\end{table}
+
+La funzione prende sempre come primo argomento un file descriptor di
+\textit{epoll}, \param{epfd}, che deve essere stato ottenuto in precedenza con
+una chiamata a \func{epoll\_create}. L'argomento \param{fd} indica invece il
+file descriptor che si vuole tenere sotto controllo, quest'ultimo può essere
+un qualunque file descriptor utilizzabile con \func{poll}, ed anche un altro
+file descriptor di \textit{epoll}, ma non lo stesso \param{epfd}.
+
+L'ultimo argomento, \param{event}, deve essere un puntatore ad una struttura
+di tipo \struct{epoll\_event}, ed ha significato solo con le operazioni
+\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD}, per le quali serve ad
+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
+  partire dal 2.6.9 si può specificare anche anche un valore \texttt{NULL}.}
+
+
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/epoll_event.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{epoll\_event}, che consente di specificare
+    gli eventi associati ad un file descriptor controllato con
+    \textit{epoll}.}
+  \label{fig:epoll_event}
+\end{figure}
+
+La struttura \struct{epoll\_event} è l'analoga di \struct{pollfd} e come
+quest'ultima serve sia in ingresso (quando usata con \func{epoll\_ctl}) ad
+impostare quali eventi osservare, che in uscita (nei risultati ottenuti con
+\func{epoll\_wait}) per ricevere le notifiche degli eventi avvenuti.  La sua
+definizione è riportata in fig.~\ref{fig:epoll_event}. 
+
+Il primo campo, \var{events}, è una maschera binaria in cui ciascun bit
+corrisponde o ad un tipo di evento, o una modalità di notifica; detto campo
+deve essere specificato come OR aritmetico delle costanti riportate in
+tab.~\ref{tab:epoll_events}. Il secondo campo, \var{data}, serve ad indicare a
+quale file descriptor si intende fare riferimento, ed in astratto può
+contenere un valore qualsiasi che permetta di identificarlo, di norma comunque
+si usa come valore lo stesso \param{fd}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{EPOLLIN}     & Il file è pronto per le operazioni di lettura
+                          (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{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{EPOLLPRI}    & Ci sono \itindex{out-of-band} dati urgenti
+                          disponibili in lettura (analogo di
+                          \const{POLLPRI}); questa condizione viene comunque
+                          riportata in uscita, e non è necessaria impostarla
+                          in ingresso.\\ 
+    \const{EPOLLERR}    & Si è verificata una condizione di errore 
+                          (analogo di \const{POLLERR}); questa condizione
+                          viene comunque riportata in uscita, e non è
+                          necessaria impostarla in ingresso.\\
+    \const{EPOLLHUP}    & Si è verificata una condizione di hung-up.\\
+    \const{EPOLLET}     & Imposta la notifica in modalità \textit{edge
+                            triggered} per il file descriptor associato.\\ 
+    \const{EPOLLONESHOT}& Imposta la modalità \textit{one-shot} per il file
+                          descriptor associato.\footnotemark\\
+    \hline    
+  \end{tabular}
+  \caption{Costanti che identificano i bit del campo \param{events} di
+    \struct{epoll\_event}.}
+  \label{tab:epoll_events}
+\end{table}
+
+\footnotetext{questa modalità è disponibile solo a partire dal kernel 2.6.2.}
+
+Le modalità di utilizzo di \textit{epoll} prevedano che si definisca qual'è
+l'insieme dei file descriptor da tenere sotto controllo tramite un certo
+\textit{epoll descriptor} \param{epfd} attraverso una serie di chiamate a
+\const{EPOLL\_CTL\_ADD}.\footnote{un difetto dell'interfaccia è che queste
+  chiamate devono essere ripetute per ciascun file descriptor, incorrendo in
+  una perdita di prestazioni qualora il numero di file descriptor sia molto
+  grande; per questo è stato proposto di introdurre come estensione una
+  funzione \func{epoll\_ctlv} che consenta di effettuare con una sola chiamata
+  le impostazioni per un blocco di file descriptor.} L'uso di
+\const{EPOLL\_CTL\_MOD} consente in seguito di modificare le modalità di
+osservazione di un file descriptor che sia già stato aggiunto alla lista di
+osservazione.
+
+Le impostazioni di default prevedono che la notifica degli eventi richiesti
+sia effettuata in modalità \textit{level triggered}, a meno che sul file
+descriptor non si sia impostata la modalità \textit{edge triggered},
+registrandolo con \const{EPOLLET} attivo nel campo \var{events}.  Si tenga
+presente che è possibile tenere sotto osservazione uno stesso file descriptor
+su due \textit{epoll descriptor} diversi, ed entrambi riceveranno le
+notifiche, anche se questa pratica è sconsigliata.
+
+Qualora non si abbia più interesse nell'osservazione di un file descriptor lo
+si può rimuovere dalla lista associata a \param{epfd} con
+\const{EPOLL\_CTL\_DEL}; si tenga conto inoltre che i file descriptor sotto
+osservazione che vengono chiusi sono eliminati dalla lista automaticamente e
+non è necessario usare \const{EPOLL\_CTL\_DEL}.
+
+Infine una particolare modalità di notifica è quella impostata con
+\const{EPOLLONESHOT}: a causa dell'implementazione di \textit{epoll} infatti
+quando si è in modalità \textit{edge triggered} l'arrivo in rapida successione
+di dati in blocchi separati\footnote{questo è tipico con i socket di rete, in
+  quanto i dati arrivano a pacchetti.} può causare una generazione di eventi
+(ad esempio segnalazioni di dati in lettura disponibili) anche se la
+condizione è già stata rilevata.\footnote{si avrebbe cioè una rottura della
+  logica \textit{edge triggered}.} 
+
+Anche se la situazione è facile da gestire, la si può evitare utilizzando
+\const{EPOLLONESHOT} per impostare la modalità \textit{one-shot}, in cui la
+notifica di un evento viene effettuata una sola volta, dopo di che il file
+descriptor osservato, pur restando nella lista di osservazione, viene
+automaticamente disattivato,\footnote{la cosa avviene contestualmente al
+  ritorno di \func{epoll\_wait} a causa dell'evento in questione.} e per
+essere riutilizzato dovrà essere riabilitato esplicitamente con una successiva
+chiamata con \const{EPOLL\_CTL\_MOD}.
+
+Una volta impostato l'insieme di file descriptor che si vogliono osservare con
+i relativi eventi, la funzione che consente di attendere l'occorrenza di uno
+di tali eventi è \funcd{epoll\_wait}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+  {int epoll\_wait(int epfd, struct epoll\_event * events, int maxevents, int
+    timeout)}
+  
+  Attende che uno dei file descriptor osservati sia pronto.
+  
+  \bodydesc{La funzione restituisce il numero di file descriptor pronti in
+    caso di successo o $-1$ in caso di errore, nel qual caso \var{errno}
+    assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] il file descriptor \param{epfd} non è valido.
+  \item[\errcode{EFAULT}] il puntatore \param{events} non è valido.
+  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
+    della scadenza di \param{timeout}.
+  \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+    con \func{epoll\_create}, o \param{maxevents} non è maggiore di zero.
+  \end{errlist}
+}
+\end{prototype}
+
+La funzione si blocca in attesa di un evento per i file descriptor registrati
+nella lista di osservazione di \param{epfd} fino ad un tempo massimo
+specificato in millisecondi tramite l'argomento \param{timeout}. Gli eventi
+registrati vengono riportati in un vettore di strutture \struct{epoll\_event}
+(che deve essere stato allocato in precedenza) all'indirizzo indicato
+dall'argomento \param{events}, fino ad un numero massimo di eventi impostato
+con l'argomento \param{maxevents}.
+
+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
+  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
+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}
+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à
+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}.
+
+
+\itindend{epoll}
 
-%\subsection{L'interfaccia di \textit{epoll}}
-%\label{sec:file_epoll}
-% placeholder ...
 
-% TODO epoll 
 
 \section{L'accesso \textsl{asincrono} ai file}
 \label{sec:file_asyncronous_access}
@@ -508,46 +905,52 @@ contesto le modalit
 \textsl{asincrona}, quelle cioè in cui un processo non deve bloccarsi in
 attesa della disponibilità dell'accesso al file, ma può proseguire
 nell'esecuzione utilizzando invece un meccanismo di notifica asincrono (di
-norma un segnale), per essere avvisato della possibilità di eseguire le
+norma un segnale, ma esistono anche altre interfacce, come \itindex{inotify}
+\textit{inotify}), per essere avvisato della possibilità di eseguire le
 operazioni di I/O volute.
 
 
-\subsection{Operazioni asincrone sui file}
+\subsection{Il \textit{Signal driven I/O}}
 \label{sec:file_asyncronous_operation}
 
-Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso l'uso
-del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei
-  comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è specifico
-  di Linux e BSD.} aprire un file in modalità asincrona, così come è possibile
-attivare in un secondo tempo questa modalità impostando questo flag attraverso
-l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
-sez.~\ref{sec:file_fcntl}). 
-
-In realtà in questo caso non si tratta di eseguire delle operazioni di lettura
-o scrittura del file in modo asincrono (tratteremo questo, che più
-propriamente è detto \textsl{I/O asincrono} in
-sez.~\ref{sec:file_asyncronous_io}), quanto di un meccanismo asincrono di
-notifica delle variazione dello stato del file descriptor aperto in questo
-modo.
-
-Quello che succede in questo caso è che il sistema genera un segnale
-(normalmente \const{SIGIO}, ma è possibile usarne altri con il comando
-\const{F\_SETSIG} di \func{fcntl}) tutte le volte che diventa possibile
-leggere o scrivere dal file descriptor che si è posto in questa modalità. Si
-può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
+Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso
+l'uso del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e
+  dei comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è
+  specifico di Linux e BSD.} aprire un file in modalità asincrona, così come è
+possibile attivare in un secondo tempo questa modalità impostando questo flag
+attraverso l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
+sez.~\ref{sec:file_fcntl}).
+
+In realtà parlare di apertura in modalità asincrona non significa che le
+operazioni di lettura o scrittura del file vengono eseguite in modo asincrono
+(tratteremo questo, che è ciò che più propriamente viene chiamato \textsl{I/O
+  asincrono}, in sez.~\ref{sec:file_asyncronous_io}), quanto dell'attivazione
+un meccanismo di notifica asincrona delle variazione dello stato del file
+descriptor aperto in questo modo.  Quello che succede in questo caso è che il
+sistema genera un segnale (normalmente \const{SIGIO}, ma è possibile usarne
+altri con il comando \const{F\_SETSIG} di \func{fcntl}) tutte le volte che
+diventa possibile leggere o scrivere dal file descriptor che si è posto in
+questa modalità.\footnote{questa modalità non è utilizzabile con i file
+  ordinari ma solo con socket, file di terminale o pseudo terminale, e, a
+  partire dal kernel 2.6, anche per fifo e pipe.}
+
+Si può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
 quale processo (o gruppo di processi) riceverà il segnale. Se pertanto si
 effettuano le operazioni di I/O in risposta alla ricezione del segnale non ci
 sarà più la necessità di restare bloccati in attesa della disponibilità di
-accesso ai file; per questo motivo Stevens chiama questa modalità
-\textit{signal driven I/O}.
-
-In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select}
-che, quando vengono usate con un numero molto grande di file descriptor, non
-hanno buone prestazioni. % TODO aggiungere cenno a epoll quando l'avrò scritta
- In tal caso infatti la maggior parte del loro tempo
-di esecuzione è impegnato ad eseguire una scansione su tutti i file descriptor
-tenuti sotto controllo per determinare quali di essi (in genere una piccola
-percentuale) sono diventati attivi.
+accesso ai file. 
+
+Per questo motivo Stevens, ed anche le pagine di manuale di
+Linux, chiamano questa modalità ``\textit{Signal driven I/O}''.  Questa è
+ancora un'altra modalità di gestione dell'I/O, alternativa all'uso di
+\itindex{epoll} \textit{epoll},\footnote{anche se le prestazioni ottenute con
+  questa tecnica sono inferiori, il vantaggio è che questa modalità è
+  utilizzabile anche con kernel che non supportano \textit{epoll}, come quelli
+  della serie 2.4, ottenendo comunque prestazioni superiori a quelle che si
+  hanno con \func{poll} e \func{select}.} che consente di evitare l'uso delle
+funzioni \func{poll} o \func{select} che, come illustrato in
+sez.~\ref{sec:file_epoll}, quando vengono usate con un numero molto grande di
+file descriptor, non hanno buone prestazioni.
 
 Tuttavia con l'implementazione classica dei segnali questa modalità di I/O
 presenta notevoli problemi, dato che non è possibile determinare, quando i
@@ -585,11 +988,16 @@ un file su cui l'accesso 
 funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
 la coda.  
 
-Se infatti si  eccedono le dimensioni di quest'ultima,  il kernel, non potendo
-più assicurare il comportamento corretto  per un segnale real-time, invierà al
-suo posto un solo \const{SIGIO}, su  cui si saranno accumulati tutti i segnali
-in  eccesso, e si  dovrà allora  determinare con  un ciclo  quali sono  i file
-diventati attivi.
+Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non potendo
+più assicurare il comportamento corretto per un segnale real-time, invierà al
+suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti i segnali
+in eccesso, e si dovrà allora determinare con un ciclo quali sono i file
+diventati attivi. L'unico modo per essere sicuri che questo non avvenga è 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
+  \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
 
@@ -603,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
-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
-  \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
-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
-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}.
@@ -735,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
-\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
@@ -752,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.
 
-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|)}
 
@@ -788,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\_MULTISHOT}& richiede una notifica permanente di tutti gli
+    \const{DN\_MULTISHOT}& Richiede una notifica permanente di tutti gli
                          eventi.\\ 
     \hline    
   \end{tabular}
@@ -797,7 +1213,6 @@ tramite il contenuto della struttura \struct{siginfo\_t}.
   \label{tab:file_notify}
 \end{table}
 
-
 Ci si può registrare per le notifiche dei cambiamenti al contenuto di una
 certa directory eseguendo la funzione \func{fcntl} su un file descriptor
 associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso
@@ -819,20 +1234,36 @@ specificare un valore nullo.
 
 \index{file!inotify|(}
 
-Il maggiore problema di \textit{dnotify} è quello della scalabilità, e della
-complessità di gestione dovuta all'uso dei segnali. Per questo motivo 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.}
+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 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_control}.  Per tutta questa serie di motivi in generale
+quella di \textit{dnotify} viene considerata una interfaccia di usabilità
+problematica.
 
 \index{file!dnotify|)}
 
-L'interfaccia di \textit{inotify} è una caratteristica 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 file
-descriptor. 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)}
   
@@ -851,34 +1282,44 @@ il cui prototipo 
 }
 \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}. 
-
-Trattandosi di file descriptor a tutti gli effetti, esso potrà essere
-utilizzato con le funzioni \func{select} e \func{poll}. Dato che gli eventi
-vengono notificati come dati disponibili in lettura sul file descriptor
-stesso, dette funzioni ritorneranno tutte le volte che si avrà un evento di
-notifica. Si potrà cioè gestirlo secondo le modalità illustrate in
-sez.~\ref{sec:file_multiplexing}. Inoltre, come per i file descriptor
-associati ai socket (vedi sez.~\ref{sec:sock_ioctl_IP}) si potrà ottenere il
-numero di byte disponibili in lettura eseguendo su di esso l'operazione
-\const{FIONREAD} con \func{ioctl}.
-
-Una volta creata la coda di notifica, ed ottenuto il relativo file descriptor,
-l'interfaccia prevede che si definiscano gli eventi da tenere sotto
-osservazione associando ad esso una \textsl{lista di osservazione} (o
-\textit{watch list}) che indica quali file e directory tenere d'occhio. Per
-gestire la lista di osservazione l'interfaccia fornisce due funzioni, la prima
-di queste è \funcd{inotify\_add\_watch}, il cui prototipo è:
+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à
+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 sul file descriptor, 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 delle
+modifiche con una qualunque delle modalità di \textit{I/O multiplexing}
+illustrate in sez.~\ref{sec:file_multiplexing}.
+
+Infine l'interfaccia di \textit{inotify} consente di mettere sotto
+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)}
 
   Aggiunge un evento di osservazione alla lista di osservazione di \param{fd}.
-  
+
   \bodydesc{La funzione restituisce un valore positivo in caso di successo, o
     $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
@@ -891,59 +1332,152 @@ di queste 
   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 osservazione di una coda di
-notifica. Quest'ultima viene identificata specificando il file descriptor ad
-essa associato nell'argomento \param{fd}. Il file da porre sotto osservazione
-viene invece identificato tramite il suo pathname passato nell'argomento
-\param{pathname}, infine il terzo argomento, \param{mask}, è una maschera
-binaria che consente di specificare quali tipologie di eventi accaduti sul
-file devono essere osservati, e deve essere specificato con una OR aritmetico
-delle costanti riportate in tab.~\ref{tab:inotify_event_watch}.
-
+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
   \footnotesize
-  \begin{tabular}[c]{|l|p{8cm}|}
+  \begin{tabular}[c]{|l|c|p{10cm}|}
     \hline
-    \textbf{Valore}  & \textbf{Significato} \\
+    \textbf{Flag}  & & \textbf{Significato} \\
     \hline
     \hline
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
-    \const{}& .\\ 
+    \const{IN\_ACCESS}        &$\bullet$& C'è stato accesso al file in
+                                          lettura.\\  
+    \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.\\  
+    \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.\\  
+    \const{IN\_DELETE}        &$\bullet$& È stato cancellato un file o una
+                                          directory in una directory sotto
+                                          osservazione.\\ 
+    \const{IN\_DELETE\_SELF}  &       &   È stato cancellato il file (o la
+                                          directory) sotto osservazione.\\ 
+    \const{IN\_MODIFY}        &$\bullet$& È stato modificato il file.\\ 
+    \const{IN\_MOVE\_SELF}    &         & è stato rinominato il file (o la
+                                          directory) sotto osservazione.\\ 
+    \const{IN\_MOVED\_FROM}   &$\bullet$& Un file è stato spostato fuori dalla
+                                          directory sotto osservazione.\\ 
+    \const{IN\_MOVED\_TO}     &$\bullet$& Un file è stato spostato nella
+                                          directory sotto osservazione.\\ 
+    \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}
   \caption{Le costanti che identificano i valori per la maschera binaria
-    dell'argomento \param{mask} di \func{inotify\_add\_watch}.} 
+    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}
 
+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.
 
-Dato che può esistere un solo \textit{watch} per file, qualora venga
-specificato il pathname di un file che era già stato posto in osservazione, 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 prototito è:
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Flag}  & \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 valori per la 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},
+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 soltato 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}; è tramite questo valore che si identifica
+univocamente un \textsl{osservatore} su una coda di notifica, sia per quanto
+riguarda i risultati restituiti da \textit{inotify}, che per quanto riguarda
+la eventuale rimozione dello stesso; la seconda funzione per la gestione delle
+liste di osservazione è infatti \funcd{inotify\_rm\_watch}, che permette di
+rimuovere un \textsl{osservatore}; il suo prototipo è:
 \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:
@@ -956,18 +1490,77 @@ usando la seconda funzione dell'interfaccia di gestione,
 }
 \end{prototype}
 
+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}.} inoltre, contemporaneamente alla rimozione
+dell'osservatore, sulla coda di notifica verrà generato un evento di tipo
+\const{IN\_IGNORED} (vedi tab.~\ref{tab:inotify_read_event_flag}).
+
+
+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}; questi ultimi infatti vengono notificati alle
+applicazioni che usano l'interfaccia di \textit{inotify} come dati presenti in
+lettura su file descriptor creato con \func{inotify\_init}. 
+
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/inotify_event.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{inotify\_event}.}
+  \label{fig:inotify_event}
+\end{figure}
+
+
+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{Flag}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IN\_IGNORED}    & .\\
+    \const{IN\_ISDIR}      & .\\
+    \const{IN\_Q\_OVERFLOW}& .\\
+    \const{IN\_UNMOUNT}    & .\\
+    \hline    
+  \end{tabular}
+  \caption{Le costanti che identificano i flag aggiuntivi usati nella maschera
+    binaria del campo \var{mask} di \structd{inotify\_event}.} 
+  \label{tab:inotify_read_event_flag}
+\end{table}
+
+
+
 % TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
 % TODO e man inotify
 
 \index{file!inotify|)}
 
 
-
-
+% TODO inserire anche eventfd (vedi http://lwn.net/Articles/233462/)
+% e le restanti signalfd e timerfd introdotte con il 2.6.22
+% o trovargli un posto migliore
 
 
 \subsection{L'interfaccia POSIX per l'I/O asincrono}
@@ -1205,7 +1798,7 @@ operazioni di sincronizzazione dei dati saranno completate.
 
 In alcuni casi può essere necessario interrompere le operazioni (in genere
 quando viene richiesta un'uscita immediata dal programma), per questo lo
-standard POSIX.1b prevede una funzioni apposita, \funcd{aio\_cancel}, che
+standard POSIX.1b prevede una funzione apposita, \funcd{aio\_cancel}, che
 permette di cancellare una operazione richiesta in precedenza; il suo
 prototipo è:
 \begin{prototype}{aio.h}
@@ -1564,7 +2157,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
-                             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
@@ -1572,7 +2165,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
-                             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
@@ -1582,13 +2175,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
-                             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\_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}
@@ -1596,7 +2189,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
-                             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 
@@ -1614,9 +2207,9 @@ tab.~\ref{tab:file_mmap_flag}.
                              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
-                             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.\\
@@ -1970,7 +2563,7 @@ nuova system call, \funcd{remap\_file\_pages}, il cui prototipo 
   
   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}
     \item[\errcode{EINVAL}] Si è usato un valore non valido per uno degli
@@ -2033,24 +2626,95 @@ mappatura che gi
 \itindend{memory~mapping}
 
 
-\subsection{L'I/O diretto fra file descriptor con \func{sendfile}}
-\label{sec:file_sendfile}
+\subsection{L'I/O diretto fra file descriptor}
+\label{sec:file_sendfile_splice}
 
-Uno dei problemi 
 
-NdA è da finire, sul perché non è abilitata fra file vedi:
+Uno dei problemi che si presenta 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à sarebbe molto più
+efficiente tenere 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}; 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,
+per cui vengono utilizzati diversi prototipi e semantiche
+differenti;\footnote{pertanto si eviti di utilizzarla se si devono scrivere
+  programmi portabili.} nel caso di Linux il suo prototipo è:
+\begin{functions}  
+  \headdecl{sys/sendfile.h} 
+
+  \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 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}] 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
+      o una operazione di \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}
+
+
+%NdA è da finire, sul perché non è abilitata fra file vedi:
+%\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}}
+
 
-\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}}
 % 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)
+% e http://kerneltrap.org/node/6505
 
 
 
-% i raw device 
-%\subsection{I \textit{raw} device}
-%\label{sec:file_raw_device}
-%
-% TODO i raw device
+
+\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.
+
+
+% TODO documentare \func{madvise}
+% TODO documentare \func{mincore}
+% 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}
+% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
 
 
 %\subsection{L'utilizzo delle porte di I/O}
@@ -2796,7 +3460,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
-                      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
@@ -2946,10 +3610,17 @@ possibilit
 % LocalWords:  flock shared exclusive operation dup inode linked NFS cmd ENOLCK
 % LocalWords:  EDEADLK whence SEEK CUR type pid GETLK SETLK SETLKW all'inode HP
 % LocalWords:  switch bsd lockf mandatory SVr sgid group root mount mand TRUNC
-% LocalWords:  SVID UX Documentation sendfile dnotify inotify NdA
+% LocalWords:  SVID UX Documentation sendfile dnotify inotify NdA ppoll fds add
+% LocalWords:  init EMFILE FIONREAD ioctl watch char pathname uint mask ENOSPC
+% LocalWords:  dell'inode CLOSE NOWRITE MOVE MOVED FROM TO rm wd event page ctl
+% 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 ctlv ALL DONT HPUX
 
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
+% LocalWords:  FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching