+Abbiamo visto in sez.~\ref{sec:sig_gen_beha}, affrontando la suddivisione fra
+\textit{fast} e \textit{slow} \textit{system call},\index{system~call~lente}
+che in certi casi le funzioni di I/O eseguite su un file descriptor possono
+bloccarsi indefinitamente. Questo non avviene mai per i file normali, per i
+quali le funzioni di lettura e scrittura ritornano sempre subito, ma può
+avvenire per alcuni \index{file!di~dispositivo} file di dispositivo, come ad
+esempio una seriale o un terminale, o con l'uso di file descriptor collegati a
+meccanismi di intercomunicazione come le \textit{pipe} (vedi
+sez.~\ref{sec:ipc_unix}) ed i socket (vedi sez.~\ref{sec:sock_socket_def}). In
+casi come questi ad esempio una operazione di lettura potrebbe bloccarsi se
+non ci sono dati disponibili sul descrittore su cui la si sta effettuando.
+
+Questo comportamento è alla radice di una delle problematiche più comuni che
+ci si trova ad affrontare nella gestione delle operazioni di I/O: la necessità
+di operare su più file descriptor eseguendo funzioni che possono bloccarsi
+indefinitamente senza che sia possibile prevedere quando questo può
+avvenire. Un caso classico è quello di un server di rete (tratteremo la
+problematica in dettaglio nella seconda parte della guida) in attesa di dati
+in ingresso prevenienti da vari client.
+
+In un caso di questo tipo, se si andasse ad operare sui vari file descriptor
+aperti uno dopo l'altro, potrebbe accadere di restare bloccati nell'eseguire
+una lettura su uno di quelli che non è ``\textsl{pronto}'', quando ce ne
+potrebbe essere un altro con dati disponibili. Questo comporta nel migliore
+dei casi una operazione ritardata inutilmente nell'attesa del completamento di
+quella bloccata, mentre nel peggiore dei casi, quando la conclusione
+dell'operazione bloccata dipende da quanto si otterrebbe dal file descriptor
+``\textsl{disponibile}'', si potrebbe addirittura arrivare ad un
+\itindex{deadlock} \textit{deadlock}.
+
+Abbiamo già accennato in sez.~\ref{sec:file_open_close} che è possibile
+prevenire questo tipo di comportamento delle funzioni di I/O aprendo un file
+in \textsl{modalità non-bloccante}, attraverso l'uso del flag
+\const{O\_NONBLOCK} nella chiamata di \func{open}. In questo caso le funzioni
+di lettura o scrittura eseguite sul file che si sarebbero bloccate ritornano
+immediatamente, restituendo l'errore \errcode{EAGAIN}. L'utilizzo di questa
+modalità di I/O permette di risolvere il problema controllando a turno i vari
+file descriptor, in un ciclo in cui si ripete l'accesso fintanto che esso non
+viene garantito. Ovviamente questa tecnica, detta \itindex{polling}
+\textit{polling}, è estremamente inefficiente: si tiene costantemente
+impiegata la CPU solo per eseguire in continuazione delle \textit{system call}
+che nella gran parte dei casi falliranno.
+
+É appunto per superare questo problema è stato introdotto il concetto di
+\textit{I/O multiplexing}, una nuova modalità per la gestione dell'I/O che
+consente di tenere sotto controllo più file descriptor in contemporanea,
+permettendo di bloccare un processo quando le operazioni di lettura o
+scrittura non sono immediatamente effettuabili, e di riprenderne l'esecuzione
+una volta che almeno una di quelle che erano state richieste diventi
+possibile, in modo da poterla eseguire con la sicurezza di non restare
+bloccati.
+
+Dato che, come abbiamo già accennato, per i normali file su disco non si ha
+mai un accesso bloccante, l'uso più comune delle funzioni che esamineremo nei
+prossimi paragrafi è per i server di rete, in cui esse vengono utilizzate per
+tenere sotto controllo dei socket; pertanto ritorneremo su di esse con
+ulteriori dettagli e qualche esempio di utilizzo concreto in
+sez.~\ref{sec:TCP_sock_multiplexing}.
+
+
+\subsection{Le funzioni \func{select} e \func{pselect}}
+\label{sec:file_select}
+
+Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
+ multiplexing} è stato BSD, con la funzione \funcd{select} che è apparsa in
+BSD4.2 ed è stata standardizzata in BSD4.4, in seguito è stata portata su
+tutti i sistemi che supportano i socket, compreso le varianti di System V ed
+inserita in POSIX.1-2001; il suo prototipo è:\footnote{l'header
+ \texttt{sys/select.h} è stato introdotto con POSIX.1-2001, è ed presente con
+ le \acr{glibc} a partire dalla versione 2.0, in precedenza, con le
+ \acr{libc4} e le \acr{libc5}, occorreva includere \texttt{sys/time.h},
+ \texttt{sys/types.h} e \texttt{unistd.h}.}
+
+\begin{funcproto}{
+\fhead{sys/select.h}
+\fdecl{int select(int ndfs, fd\_set *readfds, fd\_set *writefds, fd\_set
+ *exceptfds, \\
+\phantom{int select(}struct timeval *timeout)}
+\fdesc{Attende che uno fra i file descriptor degli insiemi specificati diventi
+ attivo.}
+}
+{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}] si è specificato un file descriptor non valido
+ (chiuso o con errori) in uno degli insiemi.
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+ \item[\errcode{EINVAL}] si è specificato per \param{ndfs} un valore negativo
+ o un valore non valido per \param{timeout}.
+ \end{errlist}
+ ed inoltre \errval{ENOMEM} nel suo significato generico.}
+\end{funcproto}
+
+La funzione mette il processo in stato di \textit{sleep} (vedi
+tab.~\ref{tab:proc_proc_states}) fintanto che almeno uno dei file descriptor
+degli insiemi specificati (\param{readfds}, \param{writefds} e
+\param{exceptfds}), non diventa attivo, per un tempo massimo specificato da
+\param{timeout}.
+
+\itindbeg{file~descriptor~set}
+
+Per specificare quali file descriptor si intende selezionare la funzione usa
+un particolare oggetto, il \textit{file descriptor set}, identificato dal tipo
+\type{fd\_set}, che serve ad identificare un insieme di file descriptor, in
+maniera analoga a come un \itindex{signal~set} \textit{signal set} (vedi
+sez.~\ref{sec:sig_sigset}) identifica un insieme di segnali. Per la
+manipolazione di questi \textit{file descriptor set} si possono usare delle
+opportune macro di preprocessore:
+
+{\centering
+\vspace{3pt}
+\begin{funcbox}{
+\fhead{sys/select.h}
+\fdecl{void \macro{FD\_ZERO}(fd\_set *set)}
+\fdesc{Inizializza l'insieme (vuoto).}
+\fdecl{void \macro{FD\_SET}(int fd, fd\_set *set)}
+\fdesc{Inserisce il file descriptor \param{fd} nell'insieme.}
+\fdecl{void \macro{FD\_CLR}(int fd, fd\_set *set)}
+\fdesc{Rimuove il file descriptor \param{fd} dall'insieme.}
+\fdecl{int \macro{FD\_ISSET}(int fd, fd\_set *set)}
+\fdesc{Controlla se il file descriptor \param{fd} è nell'insieme.}
+}
+\end{funcbox}}
+
+
+In genere un \textit{file descriptor set} può contenere fino ad un massimo di
+\const{FD\_SETSIZE} file descriptor. Questo valore in origine corrispondeva
+al limite per il numero massimo di file aperti (ad esempio in Linux, fino alla
+serie 2.0.x, c'era un limite di 256 file per processo), ma da quando, nelle
+versioni più recenti del kernel, questo limite è stato rimosso, esso indica le
+dimensioni massime dei numeri usati nei \textit{file descriptor set}, ed il
+suo valore, secondo lo standard POSIX 1003.1-2001, è definito in
+\headfile{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. 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
+effettuare una lettura,\footnote{per essere precisi la funzione ritornerà in
+ tutti i casi in cui la successiva esecuzione di \func{read} risulti non
+ bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo,
+\param{writefds}, per verificare la possibilità di effettuare una scrittura ed
+il terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni come i
+dati urgenti \itindex{out-of-band} su un socket, (vedi
+sez.~\ref{sec:TCP_urgent_data}).
+
+Dato che in genere non si tengono mai sotto controllo fino a
+\const{FD\_SETSIZE} file contemporaneamente, la funzione richiede di
+specificare qual è il valore più alto fra i file descriptor indicati nei tre
+insiemi precedenti. Questo viene fatto per efficienza, per evitare di passare
+e far controllare al kernel una quantità di memoria superiore a quella
+necessaria. Questo limite viene indicato tramite l'argomento \param{ndfs}, che
+deve corrispondere al valore massimo aumentato di uno. Si ricordi infatti 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}, espresso con il puntatore ad una struttura
+di tipo \struct{timeval} (vedi fig.~\ref{fig:sys_timeval_struct}) 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, e così può essere utilizzata eseguire il \itindex{polling}
+\textit{polling} su un gruppo di file descriptor. Usare questo argomento con
+tutti i \textit{file descriptor set} vuoti è un modo portabile, disponibile
+anche su sistemi in cui non sono disponibili le funzioni avanzate di
+sez.~\ref{sec:sig_timer_adv}, per tenere un processo in stato di
+\textit{sleep} con precisioni inferiori al secondo.
+
+In caso di successo la funzione restituisce il numero di file descriptor
+pronti, seguendo il comportamento previsto dallo standard
+POSIX.1-2001,\footnote{si tenga però presente che esistono alcune versioni di
+ Unix che non si comportano in questo modo, restituendo un valore positivo
+ generico.} e ciascun insieme viene sovrascritto per indicare quali sono i
+file descriptor pronti per le operazioni ad esso relative, in modo da poterli
+controllare con \macro{FD\_ISSET}. Se invece scade il tempo indicato
+da \param{timout} viene restituito un valore nullo e i \textit{file descriptor
+ set} non vengono modificati. In caso di errore la funzione restituisce $-1$, i
+valori dei tre insiemi e di \param{timeout} sono indefiniti e non si può fare
+nessun affidamento sul loro contenuto; nelle versioni più recenti della
+funzione invece i \textit{file descriptor set} non vengono modificati anche in
+caso di errore.
+
+Si tenga presente infine che su Linux, in caso di programmazione
+\textit{multi-thread} se un file descriptor viene chiuso in un altro
+\textit{thread} rispetto a quello in cui si sta usando \func{select}, questa
+non subisce nessun effetto. In altre varianti di sistemi unix-like invece
+\func{select} ritorna indicando che il file descriptor è pronto, con
+conseguente possibile errore nel caso lo si usi senza che sia stato
+riaperto. Lo standard non prevede niente al riguardo e non si deve dare per
+assunto nessuno dei due comportamenti se si vogliono scrivere programmi
+portabili.
+
+
+\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
+\func{select} fornisce solo di un suggerimento, esistono infatti condizioni in
+cui \func{select} può riportare in maniera spuria che un file descriptor è
+pronto, ma l'esecuzione di una operazione di I/O si bloccherebbe: ad esempio
+con Linux questo avviene quando su un socket arrivano dei dati che poi vengono
+scartati perché corrotti (ma sono possibili pure altri casi); in tal caso pur
+risultando il relativo file descriptor pronto in lettura una successiva
+esecuzione di una \func{read} si bloccherebbe. Per questo motivo quando si usa
+l'\textit{I/O multiplexing} è sempre raccomandato l'uso delle funzioni di
+lettura e scrittura in modalità non bloccante.
+
+Su Linux quando la \textit{system call} \func{select} viene interrotta da un
+segnale modifica il valore nella struttura puntata da \param{timeout},
+impostandolo al tempo restante. In tal caso infatti si ha un errore di
+\errcode{EINTR} ed occorre rilanciare la funzione per proseguire l'attesa, ed
+in questo modo non è necessario ricalcolare tutte le volte il tempo
+rimanente. Questo può causare problemi di portabilità sia quando si usa codice
+scritto su Linux che legge questo valore, sia quando si usano programmi
+scritti per altri sistemi che non dispongono di questa caratteristica e
+ricalcolano \param{timeout} tutte le volte. In genere questa caratteristica è
+disponibile nei sistemi che derivano da System V e non è disponibile per
+quelli che derivano da BSD; lo standard POSIX.1-2001 non permette questo
+comportamento e per questo motivo le \acr{glibc} nascondono il comportamento
+passando alla \textit{system call} una copia dell'argomento \param{timeout}.
+
+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{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
+tenere sotto controllo, la funzione è nata quando il kernel consentiva un
+numero massimo di 1024 file descriptor per processo, adesso che il numero può
+essere arbitrario si viene a creare una dipendenza del tutto artificiale dalle
+dimensioni della struttura \type{fd\_set}, che può necessitare di essere
+estesa, con ulteriori perdite di prestazioni.
+
+Lo standard POSIX è rimasto a lungo senza primitive per l'\textit{I/O
+ multiplexing}, introdotto solo con le ultime revisioni dello standard (POSIX
+1003.1g-2000 e POSIX 1003.1-2001). La scelta è stata quella di seguire
+l'interfaccia creata da BSD, ma prevede che tutte le funzioni ad esso relative
+vengano dichiarate nell'header \headfile{sys/select.h}, che sostituisce i
+precedenti, ed inoltre aggiunge a \func{select} una nuova funzione
+\funcd{pselect},\footnote{il supporto per lo standard POSIX 1003.1-2001, ed
+ l'header \headfile{sys/select.h}, compaiono in Linux a partire dalle
+ \acr{glibc} 2.1. Le \acr{libc4} e \acr{libc5} non contengono questo header,
+ le \acr{glibc} 2.0 contengono una definizione sbagliata di \func{psignal},
+ senza l'argomento \param{sigmask}, la definizione corretta è presente dalle
+ \acr{glibc} 2.1-2.2.1 se si è definito \macro{\_GNU\_SOURCE} e nelle
+ \acr{glibc} 2.2.2-2.2.4 se si è definito \macro{\_XOPEN\_SOURCE} con valore
+ maggiore di 600.} il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/select.h}
+\fdecl{int pselect(int n, fd\_set *readfds, fd\_set *writefds,
+ fd\_set *exceptfds, \\
+\phantom{int pselect(}struct timespec *timeout, sigset\_t *sigmask)}
+\fdesc{Attende che uno dei file descriptor degli insiemi specificati diventi
+ attivo.}
+}
+{La funzione ritorna il numero (anche nullo) di file descriptor che sono
+ attivi in caso di successo 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}] si è specificato per \param{ndfs} un valore negativo
+ o un valore non valido per \param{timeout}.
+ \end{errlist}
+ ed inoltre \errval{ENOMEM} nel suo significato generico.
+}
+\end{funcproto}
+
+La funzione è sostanzialmente identica a \func{select}, solo che usa una
+struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timespec_struct}) per
+indicare con maggiore precisione il timeout e non ne aggiorna il valore in
+caso di interruzione. In realtà anche in questo caso la \textit{system call}
+di Linux aggiorna il valore al tempo rimanente, ma la funzione fornita dalle
+\acr{glibc} modifica questo comportamento passando alla \textit{system call}
+una variabile locale, in modo da mantenere l'aderenza allo standard POSIX che
+richiede che il valore di \param{timeout} non sia modificato.
+
+Rispetto a \func{select} la nuova funzione prende un argomento
+aggiuntivo \param{sigmask}, un puntatore ad una maschera di segnali (si veda
+sez.~\ref{sec:sig_sigmask}). Nell'esecuzione la maschera dei segnali corrente
+viene sostituita da quella così indicata immediatamente prima di eseguire
+l'attesa, e viene poi ripristinata al ritorno della funzione. L'uso
+di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
+\textit{race condition} \itindex{race~condition} quando oltre alla presenza di
+dati sui file descriptor come nella \func{select} ordinaria, ci si deve porre
+in attesa anche dell'arrivo di un segnale.
+
+Come abbiamo visto in sez.~\ref{sec:sig_example} la tecnica classica per
+rilevare l'arrivo di un segnale è quella di utilizzare il gestore per
+impostare una \index{variabili!globali} variabile globale e controllare questa
+nel corpo principale del programma; abbiamo visto in quell'occasione come
+questo lasci spazio a possibili \itindex{race~condition} \textit{race
+ condition}, per cui diventa essenziale utilizzare \func{sigprocmask} per
+disabilitare la ricezione del segnale prima di eseguire il controllo e
+riabilitarlo dopo l'esecuzione delle relative operazioni, onde evitare
+l'arrivo di un segnale immediatamente dopo il controllo, che andrebbe perso.
+
+Nel nostro caso il problema si pone quando, oltre al segnale, si devono tenere
+sotto controllo anche dei file descriptor con \func{select}, in questo caso si
+può fare conto sul fatto che all'arrivo di un segnale essa verrebbe interrotta
+e si potrebbero eseguire di conseguenza le operazioni relative al segnale e
+alla gestione dati con un ciclo del tipo:
+\includecodesnip{listati/select_race.c}
+qui però emerge una \itindex{race~condition} \textit{race condition}, perché
+se il segnale arriva prima della chiamata a \func{select}, questa non verrà
+interrotta, e la ricezione del segnale non sarà rilevata.
+
+Per questo è stata introdotta \func{pselect} che attraverso l'argomento
+\param{sigmask} permette di riabilitare la ricezione il segnale
+contestualmente all'esecuzione della funzione,\footnote{in Linux però, fino al
+ kernel 2.6.16, non era presente la relativa \textit{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 situazione si può ricorrere ad
+ una soluzione alternativa, chiamata \itindex{self-pipe trick}
+ \textit{self-pipe trick}, che consiste nell'aprire una \textit{pipe} (vedi
+ sez.~\ref{sec:ipc_pipes}) ed usare \func{select} sul capo in lettura della
+ stessa; si può indicare l'arrivo di un segnale scrivendo sul capo in
+ scrittura all'interno del gestore dello stesso; in questo modo anche se il
+ segnale va perso prima della chiamata di \func{select} questa lo riconoscerà
+ comunque dalla presenza di dati sulla \textit{pipe}.} ribloccandolo non
+appena essa ritorna, così che il precedente codice potrebbe essere riscritto
+nel seguente modo:
+\includecodesnip{listati/pselect_norace.c}
+in questo caso utilizzando \var{oldmask} durante l'esecuzione di
+\func{pselect} la ricezione del segnale sarà abilitata, ed in caso di
+interruzione si potranno eseguire le relative operazioni.
+
+
+\subsection{Le funzioni \func{poll} e \func{ppoll}}
+\label{sec:file_poll}
+
+Nello sviluppo di System V, invece di utilizzare l'interfaccia di
+\func{select}, che è una estensione tipica di BSD, è stata introdotta una
+interfaccia completamente diversa, basata sulla funzione di sistema
+\funcd{poll},\footnote{la funzione è prevista dallo standard XPG4, ed è stata
+ introdotta in Linux come \textit{system call} a partire dal kernel 2.1.23 ed
+ inserita nelle \acr{libc} 5.4.28, originariamente l'argomento \param{nfds}
+ era di tipo \ctyp{unsigned int}, la funzione è stata inserita nello standard
+ POSIX.1-2001 in cui è stato introdotto il tipo nativo \type{nfds\_t}.} il
+cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/poll.h}
+\fdecl{int poll(struct pollfd *ufds, nfds\_t nfds, int timeout)}
+\fdesc{Attende un cambiamento di stato su un insieme di file
+ descriptor.}
+}
+
+{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}] 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 permette di tenere sotto controllo contemporaneamente \param{ndfs}
+file descriptor, specificati attraverso il puntatore \param{ufds} ad un
+vettore di strutture \struct{pollfd}. Come con \func{select} si può
+interrompere l'attesa dopo un certo tempo, questo deve essere specificato con
+l'argomento \param{timeout} in numero di millisecondi: un valore negativo
+indica un'attesa indefinita, mentre un valore nullo comporta il ritorno
+immediato, e può essere utilizzato per impiegare \func{poll} in modalità
+\textsl{non-bloccante}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{0.90\textwidth}
+ \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},
+prevede tre campi: in \var{fd} deve essere indicato il numero del file
+descriptor da controllare, in \var{events} deve essere specificata una
+maschera binaria di flag che indichino il tipo di evento che si vuole
+controllare, mentre in \var{revents} il kernel restituirà il relativo
+risultato.
+
+Usando un valore negativo per \param{fd} la corrispondente struttura sarà
+ignorata da \func{poll} ed il campo \var{revents} verrà azzerato, questo
+consente di eliminare temporaneamente un file descriptor dalla lista senza
+dover modificare il vettore \param{ufds}. Dato che i dati in ingresso sono del
+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.
+
+Le costanti che definiscono i valori relativi ai bit usati nelle maschere
+binarie dei campi \var{events} e \var{revents} sono riportate in
+tab.~\ref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono
+suddivise in tre gruppi principali, nel primo gruppo si sono indicati i bit
+utilizzati per controllare l'attività in ingresso, nel secondo quelli per
+l'attività in uscita, infine il terzo gruppo contiene dei valori che vengono
+utilizzati solo nel campo \var{revents} per notificare delle condizioni di
+errore.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Flag} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{POLLIN} & È possibile la lettura.\\
+ \const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\
+ \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari.\\
+ \const{POLLPRI} & È possibile la lettura di \itindex{out-of-band} dati
+ urgenti.\\
+ \hline
+ \const{POLLOUT} & È possibile la scrittura immediata.\\
+ \const{POLLWRNORM}& È possibile la scrittura di dati normali.\\
+ \const{POLLWRBAND}& È possibile la scrittura di dati prioritari.\\
+ \hline
+ \const{POLLERR} & C'è una condizione di errore.\\
+ \const{POLLHUP} & Si è verificato un hung-up.\\
+ \const{POLLRDHUP} & Si è avuta una \textsl{half-close} su un
+ socket.\footnotemark\\
+ \const{POLLNVAL} & Il file descriptor non è aperto.\\
+ \hline
+ \const{POLLMSG} & Definito per compatibilità con SysV.\\
+ \hline
+ \end{tabular}
+ \caption{Costanti per l'identificazione dei vari bit dei campi
+ \var{events} e \var{revents} di \struct{pollfd}.}
+ \label{tab:file_pollfd_flags}
+\end{table}
+
+\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 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 disponibilità 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, 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
+\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.
+
+\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}
+
+% era stata aggiunta EPOLL_CTL_DISABLE in previsione del kernel 3.7, vedi
+% http://lwn.net/Articles/520012/ e http://lwn.net/Articles/520198/
+% ma non è mai stata inserita.
+
+Le modalità di utilizzo di \textit{epoll} prevedono che si definisca qual'è
+l'insieme dei file descriptor da tenere sotto controllo utilizzando 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. 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}.
+
+Anche se è possibile tenere sotto controllo lo stesso file descriptor in due
+istanze distinte di \textit{epoll} in genere questo è sconsigliato in quanto
+entrambe riceveranno le notifiche, e gestire correttamente le notifiche
+multiple richiede molta attenzione. Se invece si cerca di inserire due volte
+lo stesso file descriptor nella stessa istanza di \textit{epoll} la funzione
+fallirà con un errore di \errval{EEXIST}. Tuttavia è possibile inserire nella
+stessa istanza file descriptor duplicati (si ricordi quanto visto in
+sez.~\ref{sec:file_dup}), una tecnica che può essere usata per registrarli con
+un valore diverso per \param{events} e classificare così diversi tipi di
+eventi.
+
+Si tenga presente che quando si chiude un file descriptor questo, se era stato
+posto sotto osservazione da una istanza di \textit{epoll}, viene rimosso
+automaticamente solo nel caso esso sia l'unico riferimento al file aperto
+sottostante (più precisamente alla struttura \kstruct{file}, si ricordi
+fig.~\ref{fig:file_dup}) e non è necessario usare
+\const{EPOLL\_CTL\_DEL}. Questo non avviene qualora esso sia stato duplicato
+(perché la suddetta struttura non viene disallocata) e si potranno ricevere
+eventi ad esso relativi anche dopo che lo si è chiuso; per evitare
+l'inconveniente è necessario rimuoverlo esplicitamente con
+\const{EPOLL\_CTL\_DEL}.
+
+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}. Nella prima parte della tabella si sono indicate
+le costanti che permettono di indicare il tipo di evento, che sono le
+equivalenti delle analoghe di tab.~\ref{tab:file_pollfd_flags} per
+\func{poll}. Queste sono anche quelle riportate nella struttura
+\struct{epoll\_event} restituita da \func{epoll\_wait} per indicare il tipo di
+evento presentatosi, insieme a quelle della seconda parte della tabella, che
+vengono comunque riportate anche se non le si sono impostate con
+\func{epoll\_ctl}. La terza parte della tabella contiene le costanti che
+modificano le modalità di notifica.
+
+\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.\\
+ \hline
+ \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.\\
+ \hline
+ \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).\\
+ \const{EPOLLWAKEUP} & Attiva la prevenzione della sospensione del sistema
+ se il file descriptor che si è marcato con esso
+ diventa pronto (aggiunto a partire dal kernel 3.5),
+ può essere impostato solo dall'amministratore (o da
+ un processo con la capacità
+ \const{CAP\_BLOCK\_SUSPEND}).\\
+ \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 di
+ un socket quando si lavora in modalità \textit{edge triggered}.}
+
+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.
+
+% 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}.
+
+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 di sistema 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} avviene solo quando il file descriptor ha
+cambiato stato diventando pronto. Esso non sarà riportato nuovamente fino ad
+un altro cambiamento di stato, per cui occorre assicurarsi di aver
+completamente esaurito 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}, (è 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.
+
+Si tenga presente che in modalità \textit{edge triggered}, dovendo esaurire le
+attività di I/O dei file descriptor risultati pronti per poter essere
+rinotificati, la gestione elementare per cui li si trattano uno per uno in
+sequenza può portare ad un effetto denominato \textit{starvation}
+(``\textsl{carestia}''). Si rischia cioè di concentrare le operazioni sul
+primo file descriptor che dispone di molti dati, prolungandole per tempi molto
+lunghi con un ritardo che può risultare eccessivo nei confronti di quelle da
+eseguire sugli altri che verrebbero dopo. Per evitare questo tipo di
+problematiche viene consigliato di usare \func{epoll\_wait} per registrare un
+elenco dei file descriptor da gestire, e di trattarli a turno in maniera più
+equa.
+
+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. Valgono le osservazioni fatte in
+sez.~\ref{sec:file_select}, e per poterlo fare di nuovo è necessaria una
+variante della funzione di attesa che consenta di reimpostare all'uscita una
+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 di sistema 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, \\
+\phantom{int epoll\_pwait(}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}.
+
+}
+\end{funcproto}
+
+La funzione è del tutto analoga \funcd{epoll\_wait}, soltanto che alla sua
+uscita viene ripristinata la maschera di segnali originale, sostituita durante
+l'esecuzione da quella impostata con l'argomento \param{sigmask}; in sostanza
+la chiamata a questa funzione è equivalente al seguente codice, eseguito però
+in maniera atomica:
+\includecodesnip{listati/epoll_pwait_means.c}
+
+Si tenga presente che come le precedenti funzioni di \textit{I/O multiplexing}
+anche le funzioni dell'interfaccia di \textit{epoll} vengono utilizzate
+prevalentemente con i server di rete, quando si devono tenere sotto
+osservazione un gran numero di socket; per questo motivo rimandiamo anche in
+questo caso la trattazione di un esempio concreto a quando avremo esaminato in
+dettaglio le caratteristiche dei socket; in particolare si potrà trovare un
+programma che utilizza questa interfaccia in sez.~\ref{sec:TCP_serv_epoll}.
+
+\itindend{epoll}
+
+
+\subsection{La notifica di eventi tramite file descriptor}
+\label{sec:sig_signalfd_eventfd}
+
+Abbiamo visto in sez.~\ref{sec:file_select} come il meccanismo classico delle
+notifiche di eventi tramite i segnali, presente da sempre nei sistemi
+unix-like, porti a notevoli problemi nell'interazione con le funzioni per
+l'\textit{I/O multiplexing}, tanto che per evitare possibili
+\itindex{race~condition} \textit{race condition} sono state introdotte
+estensioni dello standard POSIX e funzioni apposite come \func{pselect},
+\func{ppoll} e \funcd{epoll\_pwait}.
+
+Benché i segnali siano il meccanismo più usato per effettuare notifiche ai
+processi, la loro interfaccia di programmazione, che comporta l'esecuzione di
+una funzione di gestione in maniera asincrona e totalmente scorrelata
+dall'ordinario flusso di esecuzione del processo, si è però dimostrata quasi
+subito assai problematica. Oltre ai limiti relativi ai limiti al cosa si può
+fare all'interno della funzione del gestore di segnali (quelli illustrati in
+sez.~\ref{sec:sig_signal_handler}), c'è il problema più generale consistente
+nel fatto che questa modalità di funzionamento cozza con altre interfacce di
+programmazione previste dal sistema in cui si opera in maniera
+\textsl{sincrona}, come quelle dell'\textit{I/O multiplexing} appena
+illustrate.
+
+In questo tipo di interfacce infatti ci si aspetta che il processo gestisca
+gli eventi a cui deve reagire in maniera sincrona generando le opportune
+risposte, mentre con l'arrivo di un segnale si possono avere interruzioni
+asincrone in qualunque momento. Questo comporta la necessità di dover
+gestire, quando si deve tener conto di entrambi i tipi di eventi, le
+interruzioni delle funzioni di attesa sincrone, ed evitare possibili
+\itindex{race~condition} \textit{race conditions}. In sostanza se non ci
+fossero i segnali non ci sarebbe da preoccuparsi, fintanto che si effettuano
+operazioni all'interno di un processo, della non atomicità delle
+\index{system~call~lente} \textit{system call} lente che vengono interrotte e
+devono essere riavviate.
+
+Abbiamo visto però in sez.~\ref{sec:sig_real_time} che insieme ai segnali
+\textit{real-time} sono state introdotte anche delle interfacce di gestione
+sincrona dei segnali, con la funzione \func{sigwait} e le sue affini. Queste
+funzioni consentono di gestire i segnali bloccando un processo fino alla
+avvenuta ricezione e disabilitando l'esecuzione asincrona rispetto al resto
+del programma del gestore del segnale. Questo consente di risolvere i problemi
+di atomicità nella gestione degli eventi associati ai segnali, avendo tutto il
+controllo nel flusso principale del programma, ottenendo così una gestione
+simile a quella dell'\textit{I/O multiplexing}, ma non risolve i problemi
+delle interazioni con quest'ultimo, perché o si aspetta la ricezione di un
+segnale o si aspetta che un file descriptor sia accessibile e nessuna delle
+rispettive funzioni consente di fare contemporaneamente entrambe le cose.
+
+Per risolvere questo problema nello sviluppo del kernel si è pensato di
+introdurre un meccanismo alternativo per la notifica dei segnali (esteso anche
+ad altri eventi generici) che, ispirandosi di nuovo alla filosofia di Unix per
+cui tutto è un file, consentisse di eseguire la notifica con l'uso di
+opportuni file descriptor. Ovviamente si tratta di una funzionalità specifica
+di Linux, non presente in altri sistemi unix-like, e non prevista da nessuno
+standard, per cui va evitata se si ha a cuore la portabilità.
+
+In sostanza, come per \func{sigwait}, si può disabilitare l'esecuzione di un
+gestore in occasione dell'arrivo di un segnale, e rilevarne l'avvenuta
+ricezione leggendone la notifica tramite l'uso di uno speciale file
+descriptor. Trattandosi di un file descriptor questo potrà essere tenuto sotto
+osservazione con le ordinarie funzioni dell'\textit{I/O multiplexing} (vale a
+dire con le solite \func{select}, \func{poll} e \funcd{epoll\_wait}) allo
+stesso modo di quelli associati a file o socket, per cui alla fine si potrà
+attendere in contemporanea sia l'arrivo del segnale che la disponibilità di
+accesso ai dati relativi a questi ultimi.
+
+La funzione di sistema che permette di abilitare la ricezione dei segnali
+tramite file descriptor è \funcd{signalfd},\footnote{in realtà quella
+ riportata è l'interfaccia alla funzione fornita dalle \acr{glibc}, esistono
+ infatti due versioni diverse della \textit{system call}; una prima versione,
+ \func{signalfd}, introdotta nel kernel 2.6.22 e disponibile con le
+ \acr{glibc} 2.8 che non supporta l'argomento \texttt{flags}, ed una seconda
+ versione, \funcm{signalfd4}, introdotta con il kernel 2.6.27 e che è quella
+ che viene sempre usata a partire dalle \acr{glibc} 2.9, che prende un
+ argomento aggiuntivo \code{size\_t sizemask} che indica la dimensione della
+ maschera dei segnali, il cui valore viene impostato automaticamente dalle
+ \acr{glibc}.} il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/signalfd.h}
+\fdecl{int signalfd(int fd, const sigset\_t *mask, int flags)}
+
+\fdesc{Crea o modifica un file descriptor per la ricezione dei segnali.}
+}
+
+{La funzione ritorna un numero di file descriptor in caso di successo e $-1$
+ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il valore \param{fd} non indica un file descriptor.
+ \item[\errcode{EINVAL}] il file descriptor \param{fd} non è stato ottenuto
+ con \func{signalfd} o il valore di \param{flags} non è valido.
+ \item[\errcode{ENODEV}] il kernel non può montare internamente il
+ dispositivo per la gestione anonima degli \itindex{inode} \textit{inode}
+ associati al file descriptor.
+ \item[\errcode{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file
+ descriptor di \func{signalfd}.
+ \end{errlist}
+ ed inoltre \errval{EMFILE} e \errval{ENFILE} nel loro significato generico.
+
+}
+\end{funcproto}
+
+La funzione consente di creare o modificare le caratteristiche di un file
+descriptor speciale su cui ricevere le notifiche della ricezione di
+segnali. Per creare ex-novo uno di questi file descriptor è necessario passare
+$-1$ come valore per l'argomento \param{fd}, ogni altro valore positivo verrà
+invece interpretato come il numero del file descriptor (che deve esser stato
+precedentemente creato sempre con \func{signalfd}) di cui si vogliono
+modificare le caratteristiche. Nel primo caso la funzione ritornerà il valore
+del nuovo file descriptor e nel secondo caso il valore indicato
+con \param{fd}, in caso di errore invece verrà restituito $-1$.
+
+L'elenco dei segnali che si vogliono gestire con \func{signalfd} deve essere
+specificato tramite l'argomento \param{mask}. Questo deve essere passato come
+puntatore ad una maschera di segnali creata con l'uso delle apposite macro già
+illustrate in sez.~\ref{sec:sig_sigset}. La maschera deve indicare su quali
+segnali si intende operare con \func{signalfd}; l'elenco può essere modificato
+con una successiva chiamata a \func{signalfd}. Dato che \signal{SIGKILL} e
+\signal{SIGSTOP} non possono essere intercettati (e non prevedono neanche la
+possibilità di un gestore) un loro inserimento nella maschera verrà ignorato
+senza generare errori.
+
+L'argomento \param{flags} consente di impostare direttamente in fase di
+creazione due flag per il file descriptor analoghi a quelli che si possono
+impostare con una creazione ordinaria con \func{open}, evitando una
+impostazione successiva con \func{fcntl} (si ricordi che questo è un argomento
+aggiuntivo, introdotto con la versione fornita a partire dal kernel 2.6.27,
+per kernel precedenti il valore deve essere nullo). L'argomento deve essere
+specificato come maschera binaria dei valori riportati in
+tab.~\ref{tab:signalfd_flags}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{SFD\_NONBLOCK}& imposta sul file descriptor il flag di
+ \const{O\_NONBLOCK} per renderlo non bloccante.\\
+ \const{SFD\_CLOEXEC}& imposta il flag di \const{O\_CLOEXEC} per la
+ chiusura automatica del file descriptor nella
+ esecuzione di \func{exec}.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{flags} per la funzione \func{signalfd}
+ che consentono di impostare i flag del file descriptor.}
+ \label{tab:signalfd_flags}
+\end{table}
+
+Si tenga presente che la chiamata a \func{signalfd} non disabilita la gestione
+ordinaria dei segnali indicati da \param{mask}; questa, se si vuole effettuare
+la ricezione tramite il file descriptor, dovrà essere disabilitata
+esplicitamente bloccando gli stessi segnali con \func{sigprocmask}, altrimenti
+verranno comunque eseguite le azioni di default (o un eventuale gestore
+installato in precedenza). Il blocco non ha invece nessun effetto sul file
+descriptor restituito da \func{signalfd}, dal quale sarà possibile pertanto
+ricevere qualunque segnale, anche se questo risultasse bloccato.
+
+Si tenga presente inoltre che la lettura di una struttura
+\struct{signalfd\_siginfo} relativa ad un segnale pendente è equivalente alla
+esecuzione di un gestore, vale a dire che una volta letta il segnale non sarà
+più pendente e non potrà essere ricevuto, qualora si ripristino le normali
+condizioni di gestione, né da un gestore, né dalla funzione \func{sigwaitinfo}.
+
+Come anticipato, essendo questo lo scopo principale della nuova interfaccia,
+il file descriptor può essere tenuto sotto osservazione tramite le funzioni
+dell'\textit{I/O multiplexing} (vale a dire con le solite \func{select},
+\func{poll} e \funcd{epoll\_wait}), e risulterà accessibile in lettura quando
+uno o più dei segnali indicati tramite \param{mask} sarà pendente.
+
+La funzione può essere chiamata più volte dallo stesso processo, consentendo
+così di tenere sotto osservazione segnali diversi tramite file descriptor
+diversi. Inoltre è anche possibile tenere sotto osservazione lo stesso segnale
+con più file descriptor, anche se la pratica è sconsigliata; in tal caso la
+ricezione del segnale potrà essere effettuata con una lettura da uno qualunque
+dei file descriptor a cui è associato, ma questa potrà essere eseguita
+soltanto una volta. Questo significa che tutti i file descriptor su cui è
+presente lo stesso segnale risulteranno pronti in lettura per le funzioni di
+\textit{I/O multiplexing}, ma una volta eseguita la lettura su uno di essi il
+segnale sarà considerato ricevuto ed i relativi dati non saranno più
+disponibili sugli altri file descriptor, che (a meno di una ulteriore
+occorrenza del segnale nel frattempo) di non saranno più pronti.
+
+Quando il file descriptor per la ricezione dei segnali non serve più potrà
+essere chiuso con \func{close} liberando tutte le risorse da esso allocate. In
+tal caso qualora vi fossero segnali pendenti questi resteranno tali, e
+potranno essere ricevuti normalmente una volta che si rimuova il blocco
+imposto con \func{sigprocmask}.
+
+Oltre che con le funzioni dell'\textit{I/O multiplexing} l'uso del file
+descriptor restituito da \func{signalfd} cerca di seguire la semantica di un
+sistema unix-like anche con altre \textit{system call}; in particolare esso
+resta aperto (come ogni altro file descriptor) attraverso una chiamata ad
+\func{exec}, a meno che non lo si sia creato con il flag di
+\const{SFD\_CLOEXEC} o si sia successivamente impostato il
+\textit{close-on-exec} con \func{fcntl}. Questo comportamento corrisponde
+anche alla ordinaria semantica relativa ai segnali bloccati, che restano
+pendenti attraverso una \func{exec}.
+
+Analogamente il file descriptor resta sempre disponibile attraverso una
+\func{fork} per il processo figlio, che ne riceve una copia; in tal caso però
+il figlio potrà leggere dallo stesso soltanto i dati relativi ai segnali
+ricevuti da lui stesso. Nel caso di \textit{thread} viene nuovamente seguita
+la semantica ordinaria dei segnali, che prevede che un singolo \textit{thread}
+possa ricevere dal file descriptor solo le notifiche di segnali inviati
+direttamente a lui o al processo in generale, e non quelli relativi ad altri
+\textit{thread} appartenenti allo stesso processo.
+
+L'interfaccia fornita da \func{signalfd} prevede che la ricezione dei segnali
+sia eseguita leggendo i dati relativi ai segnali pendenti dal file descriptor
+restituito dalla funzione con una normalissima \func{read}. Qualora non vi
+siano segnali pendenti la \func{read} si bloccherà a meno di non aver
+impostato la modalità di I/O non bloccante sul file descriptor, o direttamente
+in fase di creazione con il flag \const{SFD\_NONBLOCK}, o in un momento
+successivo con \func{fcntl}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{0.90\textwidth}
+ \includestruct{listati/signalfd_siginfo.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{signalfd\_siginfo}, restituita in lettura da
+ un file descriptor creato con \func{signalfd}.}
+ \label{fig:signalfd_siginfo}
+\end{figure}
+
+I dati letti dal file descriptor vengono scritti sul buffer indicato come
+secondo argomento di \func{read} nella forma di una sequenza di una o più
+strutture \struct{signalfd\_siginfo} (la cui definizione si è riportata in
+fig.~\ref{fig:signalfd_siginfo}) a seconda sia della dimensione del buffer che
+del numero di segnali pendenti. Per questo motivo il buffer deve essere almeno
+di dimensione pari a quella di \struct{signalfd\_siginfo}, qualora sia di
+dimensione maggiore potranno essere letti in unica soluzione i dati relativi
+ad eventuali più segnali pendenti, fino al numero massimo di strutture
+\struct{signalfd\_siginfo} che possono rientrare nel buffer.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/FifoReporter-init.c}
+ \end{minipage}
+ \normalsize
+ \caption{Sezione di inizializzazione del codice del programma
+ \file{FifoReporter.c}.}
+ \label{fig:fiforeporter_code_init}
+\end{figure}
+
+Il contenuto di \struct{signalfd\_siginfo} ricalca da vicino quella della
+analoga struttura \struct{siginfo\_t} (illustrata in
+fig.~\ref{fig:sig_siginfo_t}) usata dall'interfaccia ordinaria dei segnali, e
+restituisce dati simili. Come per \struct{siginfo\_t} i campi che vengono
+avvalorati dipendono dal tipo di segnale e ricalcano i valori che abbiamo già
+illustrato in sez.~\ref{sec:sig_sigaction}.\footnote{si tenga presente però
+ che per un bug i kernel fino al 2.6.25 non avvalorano correttamente i campi
+ \var{ssi\_ptr} e \var{ssi\_int} per segnali inviati con \func{sigqueue}.}
+
+Come esempio di questa nuova interfaccia ed anche come esempio di applicazione
+della interfaccia di \itindex{epoll} \textit{epoll}, si è scritto un programma
+elementare che stampi sullo standard output sia quanto viene scritto da terzi
+su una \textit{named fifo}, che l'avvenuta ricezione di alcuni segnali. Il
+codice completo si trova al solito nei sorgenti allegati alla guida (nel file
+\texttt{FifoReporter.c}).
+
+In fig.~\ref{fig:fiforeporter_code_init} si è riportata la parte iniziale del
+programma in cui vengono effettuate le varie inizializzazioni necessarie per
+l'uso di \itindex{epoll} \textit{epoll} e \func{signalfd}, a partire
+(\texttt{\small 12-16}) dalla definizione delle varie variabili e strutture
+necessarie. Al solito si è tralasciata la parte dedicata alla decodifica delle
+opzioni che consentono ad esempio di cambiare il nome del file associato alla
+\textit{fifo}.
+
+Il primo passo (\texttt{\small 19-20}) è la creazione di un file descriptor
+\texttt{epfd} di \itindex{epoll} \textit{epoll} con \func{epoll\_create} che è
+quello che useremo per il controllo degli altri. É poi necessario
+disabilitare la ricezione dei segnali (nel caso \signal{SIGINT},
+\signal{SIGQUIT} e \signal{SIGTERM}) per i quali si vuole la notifica tramite
+file descriptor. Per questo prima li si inseriscono (\texttt{\small 22-25}) in
+una maschera di segnali \texttt{sigmask} che useremo con (\texttt{\small 26})
+\func{sigprocmask} per disabilitarli. Con la stessa maschera si potrà per
+passare all'uso (\texttt{\small 28-29}) di \func{signalfd} per abilitare la
+notifica sul file descriptor \var{sigfd}. Questo poi (\texttt{\small 30-33})
+dovrà essere aggiunto con \func{epoll\_ctl} all'elenco di file descriptor
+controllati con \texttt{epfd}.
+
+Occorrerà infine (\texttt{\small 35-38}) creare la \textit{named fifo} se
+questa non esiste ed aprirla per la lettura (\texttt{\small 39-40}); una
+volta fatto questo sarà necessario aggiungere il relativo file descriptor
+(\var{fifofd}) a quelli osservati da \itindex{epoll} \textit{epoll} in maniera
+del tutto analoga a quanto fatto con quello relativo alla notifica dei
+segnali.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/FifoReporter-main.c}
+ \end{minipage}
+ \normalsize
+ \caption{Ciclo principale del codice del programma \file{FifoReporter.c}.}
+ \label{fig:fiforeporter_code_body}
+\end{figure}
+
+Una volta completata l'inizializzazione verrà eseguito indefinitamente il
+ciclo principale del programma (\texttt{\small 2-45}) che si è riportato in
+fig.~\ref{fig:fiforeporter_code_body}, fintanto che questo non riceva un
+segnale di \signal{SIGINT} (ad esempio con la pressione di \texttt{C-c}). Il
+ciclo prevede che si attenda (\texttt{\small 2-3}) la presenza di un file
+descriptor pronto in lettura con \func{epoll\_wait} (si ricordi che entrambi i
+file descriptor \var{fifofd} e \var{sigfd} sono stati posti in osservazioni
+per eventi di tipo \const{EPOLLIN}) che si bloccherà fintanto che non siano
+stati scritti dati sulla \textit{fifo} o che non sia arrivato un
+segnale.\footnote{per semplificare il codice non si è trattato il caso in cui
+ \func{epoll\_wait} viene interrotta da un segnale, assumendo che tutti
+ quelli che possano interessare siano stati predisposti per la notifica
+ tramite file descriptor, per gli altri si otterrà semplicemente l'uscita dal
+ programma.}
+
+Anche se in questo caso i file descriptor pronti possono essere al più due, si
+è comunque adottato un approccio generico in cui questi verranno letti
+all'interno di un opportuno ciclo (\texttt{\small 5-44}) sul numero
+restituito da \func{epoll\_wait}, esaminando i risultati presenti nel vettore
+\var{events} all'interno di una catena di condizionali alternativi sul valore
+del file descriptor riconosciuto come pronto, controllando cioè a quale dei
+due file descriptor possibili corrisponde il campo relativo,
+\var{events[i].data.fd}.
+
+Il primo condizionale (\texttt{\small 6-24}) è relativo al caso che si sia
+ricevuto un segnale e che il file descriptor pronto corrisponda
+(\texttt{\small 6}) a \var{sigfd}. Dato che in generale si possono ricevere
+anche notifiche relativi a più di un singolo segnale, si è scelto di leggere
+una struttura \struct{signalfd\_siginfo} alla volta, eseguendo la lettura
+all'interno di un ciclo (\texttt{\small 8-24}) che prosegue fintanto che vi
+siano dati da leggere.
+
+Per questo ad ogni lettura si esamina (\texttt{\small 9-14}) se il valore di
+ritorno della funzione \func{read} è negativo, uscendo dal programma
+(\texttt{\small 11}) in caso di errore reale, o terminando il ciclo
+(\texttt{\small 13}) con un \texttt{break} qualora si ottenga un errore di
+\errcode{EAGAIN} per via dell'esaurimento dei dati. Si ricordi infatti come
+sia la \textit{fifo} che il file descriptor per i segnali siano stati aperti in
+modalità non-bloccante, come previsto per l’\textit{I/O multiplexing},
+pertanto ci si aspetta di ricevere un errore di \errcode{EAGAIN} quando non vi
+saranno più dati da leggere.
+
+In presenza di dati invece il programma proseguirà l'esecuzione stampando
+(\texttt{\small 19-20}) il nome del segnale ottenuto all'interno della
+struttura \struct{signalfd\_siginfo} letta in \var{siginf} ed il \textit{pid}
+del processo da cui lo ha ricevuto;\footnote{per la stampa si è usato il
+ vettore \var{sig\_names} a ciascun elemento del quale corrisponde il nome
+ del segnale avente il numero corrispondente, la cui definizione si è omessa
+ dal codice di fig.~\ref{fig:fiforeporter_code_init} per brevità.} inoltre
+(\texttt{\small 21-24}) si controllerà anche se il segnale ricevuto è
+\signal{SIGINT}, che si è preso come segnale da utilizzare per la terminazione
+del programma, che verrà eseguita dopo aver rimosso il file della \textit{name
+ fifo}.
+
+Il secondo condizionale (\texttt{\small 26-39}) è invece relativo al caso in
+cui ci siano dati pronti in lettura sulla \textit{fifo} e che il file
+descriptor pronto corrisponda (\texttt{\small 26}) a \var{fifofd}. Di nuovo si
+effettueranno le letture in un ciclo (\texttt{\small 28-39}) ripetendole fin
+tanto che la funzione \func{read} non restituisce un errore di
+\errcode{EAGAIN} (\texttt{\small 29-35}). Il procedimento è lo stesso adottato
+per il file descriptor associato al segnale, in cui si esce dal programma in
+caso di errore reale, in questo caso però alla fine dei dati prima di uscire
+si stampa anche (\texttt{\small 32}) un messaggio di chiusura.
+
+Se invece vi sono dati validi letti dalla \textit{fifo} si inserirà
+(\texttt{\small 36}) una terminazione di stringa sul buffer e si stamperà il
+tutto (\texttt{\small 37-38}) sullo \textit{standard output}. L'ultimo
+condizionale (\texttt{\small 40-44}) è semplicemente una condizione di cattura
+per una eventualità che comunque non dovrebbe mai verificarsi, e che porta
+alla uscita dal programma con una opportuna segnalazione di errore.
+
+A questo punto si potrà eseguire il comando lanciandolo su un terminale, ed
+osservarne le reazioni agli eventi generati da un altro terminale; lanciando
+il programma otterremo qualcosa del tipo:
+\begin{Console}
+piccardi@hain:~/gapil/sources$ \textbf{./a.out}
+FifoReporter starting, pid 4568
+\end{Console}
+%$
+e scrivendo qualcosa sull'altro terminale con:
+\begin{Console}
+root@hain:~# \textbf{echo prova > /tmp/reporter.fifo}
+\end{Console}
+si otterrà:
+\begin{Console}
+Message from fifo:
+prova
+end message
+\end{Console}
+mentre inviando un segnale:
+\begin{Console}
+root@hain:~# \textbf{kill 4568}
+\end{Console}
+si avrà:
+\begin{Console}
+Signal received:
+Got SIGTERM
+From pid 3361
+\end{Console}
+ed infine premendo \texttt{C-\bslash} sul terminale in cui è in esecuzione si
+vedrà:
+\begin{Console}
+^\\Signal received:
+Got SIGQUIT
+From pid 0
+\end{Console}
+e si potrà far uscire il programma con \texttt{C-c} ottenendo:
+\begin{Console}
+^CSignal received:
+Got SIGINT
+From pid 0
+SIGINT means exit
+\end{Console}
+
+Lo stesso paradigma di notifica tramite file descriptor usato per i segnali è
+stato adottato anche per i timer. In questo caso, rispetto a quanto visto in
+sez.~\ref{sec:sig_timer_adv}, la scadenza di un timer potrà essere letta da un
+file descriptor senza dover ricorrere ad altri meccanismi di notifica come un
+segnale o un \textit{thread}. Di nuovo questo ha il vantaggio di poter
+utilizzare le funzioni dell'\textit{I/O multiplexing} per attendere allo
+stesso tempo la disponibilità di dati o la ricezione della scadenza di un
+timer. In realtà per questo sarebbe già sufficiente \func{signalfd} per
+ricevere i segnali associati ai timer, ma la nuova interfaccia semplifica
+notevolmente la gestione e consente di fare tutto con una sola \textit{system
+ call}.
+
+Le funzioni di questa nuova interfaccia ricalcano da vicino la struttura delle
+analoghe versioni ordinarie introdotte con lo standard POSIX.1-2001, che
+abbiamo già illustrato in sez.~\ref{sec:sig_timer_adv}.\footnote{questa
+ interfaccia è stata introdotta in forma considerata difettosa con il kernel
+ 2.6.22, per cui è stata immediatamente tolta nel successivo 2.6.23 e
+ reintrodotta in una forma considerata adeguata nel kernel 2.6.25, il
+ supporto nelle \acr{glibc} è stato introdotto a partire dalla versione
+ 2.8.6, la versione del kernel 2.6.22, presente solo su questo kernel, non è
+ supportata e non deve essere usata.} La prima funzione di sistema prevista,
+quella che consente di creare un timer, è \funcd{timerfd\_create}, il cui
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/timerfd.h}
+\fdecl{int timerfd\_create(int clockid, int flags)}
+
+\fdesc{Crea un timer associato ad un file descriptor di notifica.}
+}
+
+{La funzione ritorna un numero di file descriptor in caso di successo e $-1$
+ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] l'argomento \param{clockid} non è
+ \const{CLOCK\_MONOTONIC} o \const{CLOCK\_REALTIME}, o
+ l'argomento \param{flag} non è valido, o è diverso da zero per kernel
+ precedenti il 2.6.27.
+ \item[\errcode{ENODEV}] il kernel non può montare internamente il
+ dispositivo per la gestione anonima degli \itindex{inode} \textit{inode}
+ associati al file descriptor.
+ \item[\errcode{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file
+ descriptor di \func{signalfd}.
+ \end{errlist}
+ ed inoltre \errval{EMFILE} e \errval{ENFILE} nel loro significato generico.
+}
+\end{funcproto}
+
+La funzione prende come primo argomento un intero che indica il tipo di
+orologio a cui il timer deve fare riferimento, i valori sono gli stessi delle
+funzioni dello standard POSIX-1.2001 già illustrati in
+tab.~\ref{tab:sig_timer_clockid_types}, ma al momento i soli utilizzabili sono
+\const{CLOCK\_REALTIME} e \const{CLOCK\_MONOTONIC}. L'argomento \param{flags},
+come l'analogo di \func{signalfd}, consente di impostare i flag per l'I/O non
+bloccante ed il \textit{close-on-exec} sul file descriptor
+restituito,\footnote{il flag è stato introdotto a partire dal kernel 2.6.27,
+ per le versioni precedenti deve essere passato un valore nullo.} e deve
+essere specificato come una maschera binaria delle costanti riportate in
+tab.~\ref{tab:timerfd_flags}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{TFD\_NONBLOCK}& imposta sul file descriptor il flag di
+ \const{O\_NONBLOCK} per renderlo non bloccante.\\
+ \const{TFD\_CLOEXEC}& imposta il flag di \const{O\_CLOEXEC} per la
+ chiusura automatica del file descriptor nella
+ esecuzione di \func{exec}.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{flags} per la funzione
+ \func{timerfd\_create} che consentono di impostare i flag del file
+ descriptor.}
+ \label{tab:timerfd_flags}
+\end{table}
+
+In caso di successo la funzione restituisce un file descriptor sul quale
+verranno notificate le scadenze dei timer. Come per quelli restituiti da
+\func{signalfd} anche questo file descriptor segue la semantica dei sistemi
+unix-like, in particolare resta aperto attraverso una \func{exec} (a meno che
+non si sia impostato il flag di \textit{close-on exec} con
+\const{TFD\_CLOEXEC}) e viene duplicato attraverso una \func{fork}; questa
+ultima caratteristica comporta però che anche il figlio può utilizzare i dati
+di un timer creato nel padre, a differenza di quanto avviene invece con i
+timer impostati con le funzioni ordinarie. Si ricordi infatti che, come
+illustrato in sez.~\ref{sec:proc_fork}, allarmi, timer e segnali pendenti nel
+padre vengono cancellati per il figlio dopo una \func{fork}.
+
+Una volta creato il timer con \func{timerfd\_create} per poterlo utilizzare
+occorre \textsl{armarlo} impostandone un tempo di scadenza ed una eventuale
+periodicità di ripetizione, per farlo si usa una funzione di sistema omologa
+di \func{timer\_settime} per la nuova interfaccia; questa è
+\funcd{timerfd\_settime} ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/timerfd.h}
+\fdecl{int timerfd\_settime(int fd, int flags,
+ const struct itimerspec *new\_value,\\
+\phantom{int timerfd\_settime(}struct itimerspec *old\_value)}
+
+\fdesc{Arma un timer associato ad un file descriptor di notifica.}
+}
+
+{La funzione ritorna un numero di file descriptor in caso di successo e $-1$
+ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] l'argomento \param{fd} non corrisponde ad un file
+ descriptor.
+ \item[\errcode{EFAULT}] o \param{new\_value} o \param{old\_value} non sono
+ puntatori validi.
+ \item[\errcode{EINVAL}] il file descriptor \param{fd} non è stato ottenuto
+ con \func{timerfd\_create}, o i valori di \param{flag} o dei campi
+ \var{tv\_nsec} in \param{new\_value} non sono validi.
+ \end{errlist}
+}
+\end{funcproto}
+
+In questo caso occorre indicare su quale timer si intende operare specificando
+come primo argomento il file descriptor ad esso associato, che deve essere
+stato ottenuto da una precedente chiamata a \func{timerfd\_create}. I restanti
+argomenti sono del tutto analoghi a quelli della omologa funzione
+\func{timer\_settime}, e prevedono l'uso di strutture \struct{itimerspec}
+(vedi fig.~\ref{fig:struct_itimerspec}) per le indicazioni di temporizzazione.
+
+I valori ed il significato di questi argomenti sono gli stessi che sono già
+stati illustrati in dettaglio in sez.~\ref{sec:sig_timer_adv} e non staremo a
+ripetere quanto detto in quell'occasione; per brevità si ricordi che
+con \param{new\_value.it\_value} si indica la prima scadenza del timer e
+con \param{new\_value.it\_interval} la sua periodicità. L'unica differenza
+riguarda l'argomento \param{flags} che serve sempre ad indicare se il tempo di
+scadenza del timer è da considerarsi relativo o assoluto rispetto al valore
+corrente dell'orologio associato al timer, ma che in questo caso ha come
+valori possibili rispettivamente soltanto $0$ e \const{TFD\_TIMER\_ABSTIME}
+(l'analogo di \const{TIMER\_ABSTIME}).
+
+L'ultima funzione di sistema prevista dalla nuova interfaccia è
+\funcd{timerfd\_gettime}, che è l'analoga di \func{timer\_gettime}, il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/timerfd.h}
+\fdecl{int timerfd\_gettime(int fd, struct itimerspec *curr\_value)}
+
+\fdesc{Legge l'impostazione di un timer associato ad un file descriptor di
+ notifica.}
+}