Aggiunti TODO con le cose introdotte nel 2.6.22
[gapil.git] / fileadv.tex
index 4737913a90046c33e7d9df43791a2242ebbaa9e9..1286c56ac2c3a3f2b13d42e4f1a9473d5fc7f866 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
 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
 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
 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}}
 
 
 \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}
   \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
     *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{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{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ò
   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
 
 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
   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
 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
 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
 
 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}
 
 
 \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
 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
 
 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
 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{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}
   \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}
   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
   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}).
 
 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},
 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.
 
 \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
 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
@@ -444,11 +455,30 @@ valore nullo indica che si 
 indica un errore nella chiamata, il cui codice viene riportato al solito
 tramite \var{errno}.
 
 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
 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
 
 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,373 @@ puntatore ad una struttura \struct{timespec}, gli altri argomenti comuni con
 risultati illustrati in precedenza.
 
 
 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 $-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}.
+
+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.
+
+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
+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}
 
 \section{L'accesso \textsl{asincrono} ai file}
 \label{sec:file_asyncronous_access}
@@ -508,46 +898,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
 \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.
 
 
 operazioni di I/O volute.
 
 
-\subsection{Operazioni asincrone sui file}
+\subsection{Il \textit{Signal driven I/O}}
 \label{sec:file_asyncronous_operation}
 
 \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
 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
 
 Tuttavia con l'implementazione classica dei segnali questa modalità di I/O
 presenta notevoli problemi, dato che non è possibile determinare, quando i
@@ -585,11 +981,16 @@ un file su cui l'accesso 
 funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
 la coda.  
 
 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
+  \texttt{/proc/sys/kernel/rtsig-max} allo stesso valore di quello di
+  \texttt{/proc/sys/fs/file-max}.}
 
 % TODO fare esempio che usa O_ASYNC
 
 
 % TODO fare esempio che usa O_ASYNC
 
@@ -756,7 +1157,7 @@ Per risolvere questo problema 
 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
 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à
+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}.
 
 ottenere nel gestore del segnale il file descriptor che è stato modificato
 tramite il contenuto della struttura \struct{siginfo\_t}.
 
@@ -797,7 +1198,6 @@ tramite il contenuto della struttura \struct{siginfo\_t}.
   \label{tab:file_notify}
 \end{table}
 
   \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
 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 +1219,32 @@ specificare un valore nullo.
 
 \index{file!inotify|(}
 
 
 \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 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.
 
 \index{file!dnotify|)}
 
 
 \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 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 è:
 \begin{prototype}{sys/inotify.h}
   {int inotify\_init(void)}
   
 \begin{prototype}{sys/inotify.h}
   {int inotify\_init(void)}
   
@@ -856,29 +1268,35 @@ 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
 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 è:
+\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.} 
+
+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}.
+
+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 è:
 \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}.
 \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}
   \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}
@@ -892,38 +1310,48 @@ di queste 
 \end{prototype}
 
 La funzione consente di creare un \textsl{evento di osservazione} (un
 \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}.
-
+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.
 
 \begin{table}[htb]
   \centering
   \footnotesize
 
 \begin{table}[htb]
   \centering
   \footnotesize
-  \begin{tabular}[c]{|l|p{8cm}|}
+  \begin{tabular}[c]{|l|c|p{10cm}|}
     \hline
     \hline
-    \textbf{Valore}  & \textbf{Significato} \\
+    \textbf{Valore}  & \textbf{Significato} \\
     \hline
     \hline
     \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.\\ 
+    \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    
   \end{tabular}
   \caption{Le costanti che identificano i valori per la maschera binaria
     \hline    
   \end{tabular}
   \caption{Le costanti che identificano i valori per la maschera binaria
@@ -931,15 +1359,14 @@ delle costanti riportate in tab.~\ref{tab:inotify_event_watch}.
   \label{tab:inotify_event_watch}
 \end{table}
 
   \label{tab:inotify_event_watch}
 \end{table}
 
-
-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 è:
+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. 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 è:
 \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)}
 
@@ -956,7 +1383,31 @@ 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}
+
+
+\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.
 
 
 
 
 
 
@@ -966,8 +1417,9 @@ usando la seconda funzione dell'interfaccia di gestione,
 \index{file!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}
 
 
 \subsection{L'interfaccia POSIX per l'I/O asincrono}
@@ -1205,7 +1657,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
 
 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}
 permette di cancellare una operazione richiesta in precedenza; il suo
 prototipo è:
 \begin{prototype}{aio.h}
@@ -2033,25 +2485,35 @@ mappatura che gi
 \itindend{memory~mapping}
 
 
 \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 
 
 
-Uno dei problemi 
+%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}}
 
 
-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}}
 % TODO documentare la funzione sendfile
 % 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)
 
 
 
 
 
 
-% i raw device 
-%\subsection{I \textit{raw} device}
-%\label{sec:file_raw_device}
-%
-% TODO i raw device
 
 
+%\subsection{Gestione avanzata del caching dei dati}
+%\label{sec:file_fadvise}
+
+% 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
 
 %\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}
@@ -2946,7 +3408,13 @@ 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:  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
 
 
 %%% Local Variables: 
 
 
 %%% Local Variables: