+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, detto anche
+\textit{epoll descriptor}; si tratta di un file descriptor speciale (per cui
+\func{read} e \func{write} non sono supportate) che viene associato alla
+infrastruttura utilizzata dal kernel per gestire la notifica degli eventi, e
+che può a sua volta essere messo sotto osservazione con una chiamata a
+\func{select}, \func{poll} o \func{epoll\_ctl}; in tal caso risulterà pronto
+quando saranno disponibili eventi da notificare riguardo i file descriptor da
+lui osservati.\footnote{è anche possibile inviarlo ad un altro processo
+ attraverso un socket locale (vedi sez.~\ref{sec:sock_fd_passing}) ma
+ l'operazione non ha alcun senso dato che il nuovo processo non avrà a
+ disposizione le copie dei file descriptor messe sotto osservazione tramite
+ esso.} Una volta che se ne sia terminato l'uso si potranno rilasciare tutte
+le risorse allocate chiudendolo semplicemente 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}
+
+La funzione prende sempre come primo argomento un file descriptor di
+\textit{epoll}, \param{epfd}, che indica quale istanza di \textit{epoll} usare
+e deve pertanto essere stato ottenuto in precedenza con una chiamata a
+\func{epoll\_create} o \func{epoll\_create1}. 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}.
+
+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.