+\footnotetext{si tratta di una estensione specifica di Linux, disponibile a
+ partire dal kernel 2.6.17 definendo la marco \macro{\_GNU\_SOURCE}, che
+ consente di riconoscere la chiusura in scrittura dell'altro capo di un
+ socket, situazione che si viene chiamata appunto \itindex{half-close}
+ \textit{half-close} (\textsl{mezza chiusura}) su cui torneremo con maggiori
+ dettagli in sez.~\ref{sec:TCP_shutdown}.}
+
+Il valore \const{POLLMSG} non viene utilizzato ed è definito solo per
+compatibilità con l'implementazione di System V che usa i cosiddetti
+``\textit{stream}''. Si tratta di una interfaccia specifica di SysV non
+presente in Linux, che non ha nulla a che fare con gli \textit{stream} delle
+librerie standard del C visti in sez.~\ref{sec:file_stream}. Da essa derivano
+i nomi di alcune costanti poiché per quegli \textit{stream} sono definite tre
+classi di dati: \textsl{normali}, \textit{prioritari} ed \textit{urgenti}. In
+Linux la distinzione ha senso solo per i dati urgenti \itindex{out-of-band}
+dei socket (vedi sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come
+\func{poll} reagisce alle varie condizioni dei socket torneremo in
+sez.~\ref{sec:TCP_serv_poll}, dove vedremo anche un esempio del suo utilizzo.
+
+Le costanti relative ai diversi tipi di dati normali e prioritari che fanno
+riferimento alle implementazioni in stile System V sono \const{POLLRDNORM},
+\const{POLLWRNORM}, \const{POLLRDBAND} e \const{POLLWRBAND}. Le prime due sono
+equivalenti rispettivamente a \const{POLLIN} e \const{POLLOUT},
+\const{POLLRDBAND} non viene praticamente mai usata su Linux mentre
+\const{POLLWRBAND} ha senso solo sui socket. In ogni caso queste costanti sono
+utilizzabili soltanto qualora si sia definita la macro
+\macro{\_XOPEN\_SOURCE}.
+
+In caso di successo \func{poll} ritorna restituendo il numero di file (un
+valore positivo) per i quali si è verificata una delle condizioni di attesa
+richieste o per i quali si è verificato un errore, avvalorando i relativi bit
+di \var{revents}. In caso di errori sui file vengono utilizzati i valori della
+terza sezione di tab.~\ref{tab:file_pollfd_flags} che hanno significato solo
+per \var{revents} (se specificati in \var{events} vengono ignorati). Un valore
+di ritorno nullo indica che si è raggiunto il timeout, mentre un valore
+negativo 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. Infatti, 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}.
+
+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
+definisce la macro \macro{\_GNU\_SOURCE} ed ovviamente non deve essere usata
+se si ha a cuore la portabilità. La funzione è \funcd{ppoll}, ed il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/poll.h}
+\fdecl{int ppoll(struct pollfd *fds, nfds\_t nfds,
+ const struct timespec *timeout, \\
+\phantom{int ppoll(}const sigset\_t *sigmask)}
+
+\fdesc{Attende un cambiamento di stato su un insieme di file descriptor.}
+}
+
+{La funzione ritorna il numero di file descriptor con attività in caso di
+ successo, $0$ se c'è stato un timeout e $-1$ per un errore, nel qual caso
+ \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato in uno
+ degli insiemi.
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] il valore di \param{nfds} eccede il limite
+ \const{RLIMIT\_NOFILE}.
+ \end{errlist}
+ed inoltre \errval{EFAULT} e \errval{ENOMEM} nel loro significato generico.
+}
+\end{funcproto}
+
+La funzione ha lo stesso comportamento di \func{poll}, solo che si può
+specificare, con l'argomento \param{sigmask}, il puntatore ad una
+\index{maschera~dei~segnali} maschera di segnali; questa sarà la maschera
+utilizzata per tutto il tempo che la funzione resterà in attesa, all'uscita
+viene ripristinata la maschera originale. L'uso di questa funzione è cioè
+equivalente, come illustrato nella pagina di manuale, all'esecuzione atomica
+del seguente codice:
+\includecodesnip{listati/ppoll_means.c}
+
+Eccetto per \param{timeout}, che come per \func{pselect} deve essere un
+puntatore ad una struttura \struct{timespec}, gli altri argomenti comuni con
+\func{poll} hanno lo stesso significato, e la funzione restituisce gli stessi
+risultati illustrati in precedenza. Come nel caso di \func{pselect} la
+\textit{system call} che implementa \func{ppoll} restituisce, se la funzione
+viene interrotta da un segnale, il tempo mancante in \param{timeout}, e come
+per \func{pselect} la funzione di libreria fornita dalle \acr{glibc} maschera
+questo comportamento non modificando mai il valore di \param{timeout} anche se
+in questo caso non esiste nessuno standard che richieda questo comportamento.
+
+Infine anche per \func{poll} e \func{ppoll} valgono le considerazioni relative
+alla possibilità di avere delle notificazione spurie della disponibilita di
+accesso ai file descriptor illustrate per \func{select} in
+sez.~\ref{sec:file_select}, che non staremo a ripetere qui.
+
+\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 (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 \textit{user space} a \textit{kernel space} una lunga lista di
+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 (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 dati 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 è chiamata \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, il supporto
+ è stato aggiunto nelle \acr{glibc} a partire dalla versione 2.3.2.} anche se
+sono state in discussione altre interfacce con le quali effettuare lo stesso
+tipo di operazioni; \textit{epoll} è in grado di operare sia in modalità
+\textit{level triggered} che \textit{edge triggered}.
+
+La prima versione di \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 ma poi si è passati all'uso di
+apposite \textit{system call}. Il primo passo per usare l'interfaccia di
+\textit{epoll} è pertanto quello ottenere detto file descriptor chiamando una
+delle due funzioni di sistema \funcd{epoll\_create} e \funcd{epoll\_create1},
+i cui prototipi sono:
+
+\begin{funcproto}{
+\fhead{sys/epoll.h}
+\fdecl{int epoll\_create(int size)}
+\fdecl{int epoll\_create1(int flags)}
+
+\fdesc{Apre un file descriptor per \textit{epoll}.}
+}
+{Le funzioni ritornano un file descriptor per \textit{epoll} in caso di
+ successo e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei
+ valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] si è specificato un valore di \param{size} non
+ positivo o non valido per \param{flags}.
+ \item[\errcode{EMFILE}] si è raggiunto il limite sul numero massimo di
+ istanze di \textit{epoll} per utente stabilito da
+ \sysctlfile{fs/epoll/max\_user\_instances}.
+ \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{funcproto}
+
+Entrambe le funzioni restituiscono 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. Una volta che se ne sia
+terminato l'uso si potranno rilasciare tutte le risorse allocate chiudendolo
+come ogni altro file descriptor con \func{close}.
+
+Nel caso di \func{epoll\_create} l'argomento \param{size} serviva a dare
+l'indicazione del numero di file descriptor che si vorranno tenere sotto
+controllo, e costituiva solo un suggerimento per semplificare l'allocazione di
+risorse sufficienti, non un valore massimo, ma a partire dal kernel 2.6.8 esso
+viene totalmente ignorato e l'allocazione è sempre dinamica.
+
+La seconda versione della funzione, \func{epoll\_create1} è stata introdotta
+come estensione della precedente (è disponibile solo a partire dal kernel
+2.6.27) per poter passare dei flag di controllo come maschera binaria in fase
+di creazione del file descriptor. Al momento l'unico valore legale
+per \param{flags} (a parte lo zero) è \const{EPOLL\_CLOEXEC}, che consente di
+impostare in maniera atomica sul file descriptor il flag di
+\itindex{close-on-exec} \textit{close-on-exec} (si è trattato il significato
+di \const{O\_CLOEXEC} in sez.~\ref{sec:file_open_close}), senza che sia
+necessaria una successiva chiamata a \func{fcntl}.
+
+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 di sistema
+dell'interfaccia, \funcd{epoll\_ctl}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/epoll.h}
+\fdecl{int epoll\_ctl(int epfd, int op, int fd, struct epoll\_event *event)}
+
+\fdesc{Esegue le operazioni di controllo di \textit{epoll}.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] i 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{ENOSPC}] si è raggiunto il limite massimo di registrazioni
+ per utente di file descriptor da osservare imposto da
+ \sysctlfile{fs/epoll/max\_user\_watches}.
+ \item[\errcode{EPERM}] il file associato a \param{fd} non supporta l'uso di
+ \textit{epoll}.
+ \end{errlist}
+ }
+\end{funcproto}
+
+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}.\\
+ \const{EPOLL\_CTL\_DISABLE}& da fare.\\
+ \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}
+
+% aggiunta EPOLL_CTL_DISABLE con il kernel 3.7, vedi
+% http://lwn.net/Articles/520012/ e http://lwn.net/Articles/520198/
+
+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 un valore \val{NULL} ma se si
+ vuole mantenere la compatibilità con le versioni precedenti occorre usare un
+ puntatore valido.}
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{0.90\textwidth}
+ \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}, è una \direct{union}
+che serve a identificare il file descriptor a cui si intende fare riferimento,
+ed in astratto può contenere un valore qualsiasi (specificabile in diverse
+forme) che ne permetta una indicazione univoca. Il modo più comune di usarlo
+però è quello in cui si specifica il terzo argomento di \func{epoll\_ctl}
+nella forma \var{event.data.fd}, assegnando come valore di questo campo lo
+stesso valore dell'argomento \param{fd}, cosa che permette una immediata
+identificazione del file descriptor.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{10cm}|}
+ \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}).\footnotemark\\
+ \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; questa
+ condizione viene comunque riportata in uscita, e non
+ è necessaria impostarla in ingresso.\\
+ \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 (questa modalità è disponibile
+ solo a partire dal kernel 2.6.2).\\
+ \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.17,
+ ed è utile per riconoscere la chiusura di una connessione dall'altro capo
+ quando si lavora in modalità \textit{edge triggered}.}
+
+% TODO aggiunto EPOLLWAKEUP con il 3.5
+
+
+Le modalità di utilizzo di \textit{epoll} prevedono 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 \code{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.
+
+% TODO verificare se prima o poi epoll_ctlv verrà introdotta
+
+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 (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 (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 (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{funcproto}{
+\fhead{sys/epoll.h}
+\fdecl{int epoll\_wait(int epfd, struct epoll\_event * events, int maxevents,
+ int timeout)}
+
+\fdesc{Attende che uno dei file descriptor osservati sia pronto.}
+}
+
+{La funzione ritorna il numero di file descriptor pronti in caso di successo e
+ $-1$ per un 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{funcproto}
+
+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 (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, 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 che 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'\textit{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 per il fatto che sono stati
+restituiti meno dati di quelli richiesti.
+
+Come già per \func{select} e \func{poll} anche per l'interfaccia di
+\textit{epoll} si pone il problema di gestire l'attesa di segnali e di dati
+contemporaneamente per le osservazioni fatte in sez.~\ref{sec:file_select},
+per fare questo di nuovo è necessaria una variante della funzione di attesa
+che consenta di reimpostare all'uscita una \index{maschera~dei~segnali}
+maschera di segnali, analoga alle estensioni \func{pselect} e \func{ppoll} che
+abbiamo visto in precedenza per \func{select} e \func{poll}; in questo caso la
+funzione si chiama \funcd{epoll\_pwait}\footnote{la funzione è stata
+ introdotta a partire dal kernel 2.6.19, ed è come tutta l'interfaccia di
+ \textit{epoll}, specifica di Linux.} ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/epoll.h}
+\fdecl{int epoll\_pwait(int epfd, struct epoll\_event * events, int maxevents,
+ int timeout, const sigset\_t *sigmask)}
+
+\fdesc{Attende che uno dei file descriptor osservati sia pronto, mascherando
+ i segnali.} }
+
+{La funzione ritorna il numero di file descriptor pronti in caso di successo e
+ $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori già
+ visti con \funcd{epoll\_wait}.