+Il tipo di \textit{file lock} richiesto viene specificato dal campo
+\var{l\_type}, esso può assumere i tre valori definiti dalle costanti
+riportate in tab.~\ref{tab:file_flock_type}, che permettono di richiedere
+rispettivamente uno \textit{shared lock}, un \textit{esclusive lock}, e la
+rimozione di un blocco precedentemente acquisito. Infine il campo \var{l\_pid}
+viene usato solo in caso di lettura, quando si chiama \func{fcntl} con
+\const{F\_GETLK}, e riporta il \ids{PID} del processo che detiene il
+\textit{file lock}.
+
+Oltre a quanto richiesto tramite i campi di \struct{flock}, l'operazione
+effettivamente svolta dalla funzione è stabilita dal valore dall'argomento
+\param{cmd} che, come già riportato in sez.~\ref{sec:file_fcntl}, specifica
+l'azione da compiere; i valori relativi al \textit{file locking} sono tre:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\const{F\_GETLK}] verifica se il \textit{file lock} specificato dalla
+ struttura puntata da \param{lock} può essere acquisito: in caso negativo
+ sovrascrive la struttura \param{flock} con i valori relativi al blocco già
+ esistente che ne blocca l'acquisizione, altrimenti si limita a impostarne il
+ campo \var{l\_type} con il valore \const{F\_UNLCK}.
+\item[\const{F\_SETLK}] se il campo \var{l\_type} della struttura puntata da
+ \param{lock} è \const{F\_RDLCK} o \const{F\_WRLCK} richiede il
+ corrispondente \textit{file lock}, se è \const{F\_UNLCK} lo rilascia. Nel
+ caso la richiesta non possa essere soddisfatta a causa di un blocco
+ preesistente la funzione ritorna immediatamente con un errore di
+ \errcode{EACCES} o di \errcode{EAGAIN}.
+\item[\const{F\_SETLKW}] è identica a \const{F\_SETLK}, ma se la richiesta di
+ non può essere soddisfatta per la presenza di un altro blocco, mette il
+ processo in stato di attesa fintanto che il blocco precedente non viene
+ rilasciato. Se l'attesa viene interrotta da un segnale la funzione ritorna
+ con un errore di \errcode{EINTR}.
+\end{basedescript}
+
+Si noti che per quanto detto il comando \const{F\_GETLK} non serve a rilevare
+una presenza generica di blocco su un file, perché se ne esistono altri
+compatibili con quello richiesto, la funzione ritorna comunque impostando
+\var{l\_type} a \const{F\_UNLCK}. Inoltre a seconda del valore di
+\var{l\_type} si potrà controllare o l'esistenza di un qualunque tipo di
+blocco (se è \const{F\_WRLCK}) o di \textit{write lock} (se è
+\const{F\_RDLCK}). Si consideri poi che può esserci più di un blocco che
+impedisce l'acquisizione di quello richiesto (basta che le regioni si
+sovrappongano), ma la funzione ne riporterà sempre soltanto uno, impostando
+\var{l\_whence} a \const{SEEK\_SET} ed i valori \var{l\_start} e \var{l\_len}
+per indicare quale è la regione bloccata.
+
+Infine si tenga presente che effettuare un controllo con il comando
+\const{F\_GETLK} e poi tentare l'acquisizione con \const{F\_SETLK} non è una
+operazione atomica (un altro processo potrebbe acquisire un blocco fra le due
+chiamate) per cui si deve sempre verificare il codice di ritorno di
+\func{fcntl}\footnote{controllare il codice di ritorno delle funzioni invocate
+ è comunque una buona norma di programmazione, che permette di evitare un
+ sacco di errori difficili da tracciare proprio perché non vengono rilevati.}
+quando la si invoca con \const{F\_SETLK}, per controllare che il blocco sia
+stato effettivamente acquisito.
+
+\begin{figure}[!htb]
+ \centering \includegraphics[width=9cm]{img/file_lock_dead}
+ \caption{Schema di una situazione di \itindex{deadlock} \textit{deadlock}.}
+ \label{fig:file_flock_dead}
+\end{figure}
+
+Non operando a livello di interi file, il \textit{file locking} POSIX
+introduce un'ulteriore complicazione; consideriamo la situazione illustrata in
+fig.~\ref{fig:file_flock_dead}, in cui il processo A blocca la regione 1 e il
+processo B la regione 2. Supponiamo che successivamente il processo A richieda
+un lock sulla regione 2 che non può essere acquisito per il preesistente lock
+del processo 2; il processo 1 si bloccherà fintanto che il processo 2 non
+rilasci il blocco. Ma cosa accade se il processo 2 nel frattempo tenta a sua
+volta di ottenere un lock sulla regione A? Questa è una tipica situazione che
+porta ad un \itindex{deadlock} \textit{deadlock}, dato che a quel punto anche
+il processo 2 si bloccherebbe, e niente potrebbe sbloccare l'altro processo.
+Per questo motivo il kernel si incarica di rilevare situazioni di questo tipo,
+ed impedirle restituendo un errore di \errcode{EDEADLK} alla funzione che
+cerca di acquisire un blocco che porterebbe ad un \itindex{deadlock}
+\textit{deadlock}.
+
+Per capire meglio il funzionamento del \textit{file locking} in semantica
+POSIX (che differisce alquanto rispetto da quello di BSD, visto
+sez.~\ref{sec:file_flock}) esaminiamo più in dettaglio come viene gestito dal
+kernel. Lo schema delle strutture utilizzate è riportato in
+fig.~\ref{fig:file_posix_lock}; come si vede esso è molto simile all'analogo
+di fig.~\ref{fig:file_flock_struct}:\footnote{in questo caso nella figura si
+ sono evidenziati solo i campi di \struct{file\_lock} significativi per la
+ semantica POSIX, in particolare adesso ciascuna struttura contiene, oltre al
+ \ids{PID} del processo in \var{fl\_pid}, la sezione di file che viene
+ bloccata grazie ai campi \var{fl\_start} e \var{fl\_end}. La struttura è
+ comunque la stessa, solo che in questo caso nel campo \var{fl\_flags} è
+ impostato il bit \const{FL\_POSIX} ed il campo \var{fl\_file} non viene
+ usato.} il blocco è sempre associato \itindex{inode} all'inode, solo che in
+questo caso la titolarità non viene identificata con il riferimento ad una
+voce nella \itindex{file~table} \textit{file table}, ma con il valore del
+\ids{PID} del processo.
+
+\begin{figure}[!htb]
+ \centering \includegraphics[width=12cm]{img/file_posix_lock}
+ \caption{Schema dell'architettura del \textit{file locking}, nel caso
+ particolare del suo utilizzo secondo l'interfaccia standard POSIX.}
+ \label{fig:file_posix_lock}
+\end{figure}
+
+Quando si richiede un \textit{file lock} il kernel effettua una scansione di
+tutti i blocchi presenti sul file\footnote{scandisce cioè la
+ \itindex{linked~list} \textit{linked list} delle strutture
+ \struct{file\_lock}, scartando automaticamente quelle per cui
+ \var{fl\_flags} non è \const{FL\_POSIX}, così che le due interfacce restano
+ ben separate.} per verificare se la regione richiesta non si sovrappone ad
+una già bloccata, in caso affermativo decide in base al tipo di blocco, in
+caso negativo il nuovo blocco viene comunque acquisito ed aggiunto alla lista.
+
+Nel caso di rimozione invece questa viene effettuata controllando che il
+\ids{PID} del processo richiedente corrisponda a quello contenuto nel blocco.
+Questa diversa modalità ha delle conseguenze precise riguardo il comportamento
+dei \textit{file lock} POSIX. La prima conseguenza è che un \textit{file lock}
+POSIX non viene mai ereditato attraverso una \func{fork}, dato che il processo
+figlio avrà un \ids{PID} diverso, mentre passa indenne attraverso una
+\func{exec} in quanto il \ids{PID} resta lo stesso. Questo comporta che, al
+contrario di quanto avveniva con la semantica BSD, quando un processo termina
+tutti i \textit{file lock} da esso detenuti vengono immediatamente rilasciati.
+
+La seconda conseguenza è che qualunque file descriptor che faccia riferimento
+allo stesso file (che sia stato ottenuto con una \func{dup} o con una
+\func{open} in questo caso non fa differenza) può essere usato per rimuovere
+un blocco, dato che quello che conta è solo il \ids{PID} del processo. Da
+questo deriva una ulteriore sottile differenza di comportamento: dato che alla
+chiusura di un file i blocchi ad esso associati vengono rimossi, nella
+semantica POSIX basterà chiudere un file descriptor qualunque per cancellare
+tutti i blocchi relativi al file cui esso faceva riferimento, anche se questi
+fossero stati creati usando altri file descriptor che restano aperti.
+
+Dato che il controllo sull'accesso ai blocchi viene eseguito sulla base del
+\ids{PID} del processo, possiamo anche prendere in considerazione un altro
+degli aspetti meno chiari di questa interfaccia e cioè cosa succede quando si
+richiedono dei blocchi su regioni che si sovrappongono fra loro all'interno
+stesso processo. Siccome il controllo, come nel caso della rimozione, si basa
+solo sul \ids{PID} del processo che chiama la funzione, queste richieste
+avranno sempre successo.
+
+Nel caso della semantica BSD, essendo i lock relativi a tutto un file e non
+accumulandosi,\footnote{questa ultima caratteristica è vera in generale, se
+ cioè si richiede più volte lo stesso \textit{file lock}, o più blocchi sulla
+ stessa sezione di file, le richieste non si cumulano e basta una sola
+ richiesta di rilascio per cancellare il blocco.} la cosa non ha alcun
+effetto; la funzione ritorna con successo, senza che il kernel debba
+modificare la lista dei \textit{file lock}. In questo caso invece si possono
+avere una serie di situazioni diverse: ad esempio è possibile rimuovere con
+una sola chiamata più \textit{file lock} distinti (indicando in una regione
+che si sovrapponga completamente a quelle di questi ultimi), o rimuovere solo
+una parte di un blocco preesistente (indicando una regione contenuta in quella
+di un altro blocco), creando un buco, o coprire con un nuovo blocco altri
+\textit{file lock} già ottenuti, e così via, a secondo di come si
+sovrappongono le regioni richieste e del tipo di operazione richiesta. Il
+comportamento seguito in questo caso che la funzione ha successo ed esegue
+l'operazione richiesta sulla regione indicata; è compito del kernel
+preoccuparsi di accorpare o dividere le voci nella lista dei \textit{file
+ lock} per far si che le regioni bloccate da essa risultanti siano coerenti
+con quanto necessario a soddisfare l'operazione richiesta.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/Flock.c}
+ \end{minipage}
+ \normalsize
+ \caption{Sezione principale del codice del programma \file{Flock.c}.}
+ \label{fig:file_flock_code}
+\end{figure}
+
+Per fare qualche esempio sul \textit{file locking} si è scritto un programma che
+permette di bloccare una sezione di un file usando la semantica POSIX, o un
+intero file usando la semantica BSD; in fig.~\ref{fig:file_flock_code} è
+riportata il corpo principale del codice del programma, (il testo completo è
+allegato nella directory dei sorgenti, nel file \texttt{Flock.c}).
+
+La sezione relativa alla gestione delle opzioni al solito si è omessa, come la
+funzione che stampa le istruzioni per l'uso del programma, essa si cura di
+impostare le variabili \var{type}, \var{start} e \var{len}; queste ultime due
+vengono inizializzate al valore numerico fornito rispettivamente tramite gli
+switch \code{-s} e \cmd{-l}, mentre il valore della prima viene impostato con
+le opzioni \cmd{-w} e \cmd{-r} si richiede rispettivamente o un \textit{write
+ lock} o \textit{read lock} (i due valori sono esclusivi, la variabile
+assumerà quello che si è specificato per ultimo). Oltre a queste tre vengono
+pure impostate la variabile \var{bsd}, che abilita la semantica omonima quando
+si invoca l'opzione \cmd{-f} (il valore preimpostato è nullo, ad indicare la
+semantica POSIX), e la variabile \var{cmd} che specifica la modalità di
+richiesta del \textit{file lock} (bloccante o meno), a seconda dell'opzione
+\cmd{-b}.
+
+Il programma inizia col controllare (\texttt{\small 11--14}) che venga passato
+un argomento (il file da bloccare), che sia stato scelto (\texttt{\small
+ 15--18}) il tipo di blocco, dopo di che apre (\texttt{\small 19}) il file,
+uscendo (\texttt{\small 20--23}) in caso di errore. A questo punto il
+comportamento dipende dalla semantica scelta; nel caso sia BSD occorre
+reimpostare il valore di \var{cmd} per l'uso con \func{flock}; infatti il
+valore preimpostato fa riferimento alla semantica POSIX e vale rispettivamente
+\const{F\_SETLKW} o \const{F\_SETLK} a seconda che si sia impostato o meno la
+modalità bloccante.
+
+Nel caso si sia scelta la semantica BSD (\texttt{\small 25--34}) prima si
+controlla (\texttt{\small 27--31}) il valore di \var{cmd} per determinare se
+si vuole effettuare una chiamata bloccante o meno, reimpostandone il valore
+opportunamente, dopo di che a seconda del tipo di blocco al valore viene
+aggiunta la relativa opzione (con un OR aritmetico, dato che \func{flock}
+vuole un argomento \param{operation} in forma di maschera binaria. Nel caso
+invece che si sia scelta la semantica POSIX le operazioni sono molto più
+immediate, si prepara (\texttt{\small 36--40}) la struttura per il lock, e lo
+esegue (\texttt{\small 41}).
+
+In entrambi i casi dopo aver richiesto il blocco viene controllato il
+risultato uscendo (\texttt{\small 44--46}) in caso di errore, o stampando un
+messaggio (\texttt{\small 47--49}) in caso di successo. Infine il programma si
+pone in attesa (\texttt{\small 50}) finché un segnale (ad esempio un \cmd{C-c}
+dato da tastiera) non lo interrompa; in questo caso il programma termina, e
+tutti i blocchi vengono rilasciati.
+
+Con il programma possiamo fare varie verifiche sul funzionamento del
+\textit{file locking}; cominciamo con l'eseguire un \textit{read lock} su un
+file, ad esempio usando all'interno di un terminale il seguente comando:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -r Flock.c
+Lock acquired
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+il programma segnalerà di aver acquisito un blocco e si bloccherà; in questo
+caso si è usato il \textit{file locking} POSIX e non avendo specificato niente
+riguardo alla sezione che si vuole bloccare sono stati usati i valori
+preimpostati che bloccano tutto il file. A questo punto se proviamo ad
+eseguire lo stesso comando in un altro terminale, e avremo lo stesso
+risultato. Se invece proviamo ad eseguire un \textit{write lock} avremo:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -w Flock.c
+Failed lock: Resource temporarily unavailable
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+come ci aspettiamo il programma terminerà segnalando l'indisponibilità del
+blocco, dato che il file è bloccato dal precedente \textit{read lock}. Si noti
+che il risultato è lo stesso anche se si richiede il blocco su una sola parte
+del file con il comando:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -w -s0 -l10 Flock.c
+Failed lock: Resource temporarily unavailable
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+se invece blocchiamo una regione con:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -r -s0 -l10 Flock.c
+Lock acquired
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+una volta che riproviamo ad acquisire il \textit{write lock} i risultati
+dipenderanno dalla regione richiesta; ad esempio nel caso in cui le due
+regioni si sovrappongono avremo che:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -w -s5 -l15 Flock.c
+Failed lock: Resource temporarily unavailable
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+ed il blocco viene rifiutato, ma se invece si richiede una regione distinta
+avremo che:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -w -s11 -l15 Flock.c
+Lock acquired
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+ed il blocco viene acquisito. Se a questo punto si prova ad eseguire un
+\textit{read lock} che comprende la nuova regione bloccata in scrittura:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -r -s10 -l20 Flock.c
+Failed lock: Resource temporarily unavailable
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+come ci aspettiamo questo non sarà consentito.
+
+Il programma di norma esegue il tentativo di acquisire il lock in modalità non
+bloccante, se però usiamo l'opzione \cmd{-b} possiamo impostare la modalità
+bloccante, riproviamo allora a ripetere le prove precedenti con questa
+opzione:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -r -b -s0 -l10 Flock.c Lock acquired
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+il primo comando acquisisce subito un \textit{read lock}, e quindi non cambia
+nulla, ma se proviamo adesso a richiedere un \textit{write lock} che non potrà
+essere acquisito otterremo:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -w -s0 -l10 Flock.c
+\end{verbatim}%$
+\end{minipage}\vspace{1mm}
+\par\noindent
+il programma cioè si bloccherà nella chiamata a \func{fcntl}; se a questo
+punto rilasciamo il precedente blocco (terminando il primo comando un
+\texttt{C-c} sul terminale) potremo verificare che sull'altro terminale il
+blocco viene acquisito, con la comparsa di una nuova riga:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[piccardi@gont sources]$ ./flock -w -s0 -l10 Flock.c
+Lock acquired
+\end{verbatim}%$
+\end{minipage}\vspace{3mm}
+\par\noindent
+
+Un'altra cosa che si può controllare con il nostro programma è l'interazione
+fra i due tipi di blocco; se ripartiamo dal primo comando con cui si è
+ottenuto un blocco in lettura sull'intero file, possiamo verificare cosa
+succede quando si cerca di ottenere un blocco in scrittura con la semantica
+BSD:
+
+\vspace{1mm}
+\begin{minipage}[c]{12cm}
+\begin{verbatim}
+[root@gont sources]# ./flock -f -w Flock.c
+Lock acquired
+\end{verbatim}
+\end{minipage}\vspace{1mm}
+\par\noindent
+che ci mostra come i due tipi di blocco siano assolutamente indipendenti; per
+questo motivo occorre sempre tenere presente quale fra le due semantiche
+disponibili stanno usando i programmi con cui si interagisce, dato che i
+blocchi applicati con l'altra non avrebbero nessun effetto.
+
+
+
+\subsection{La funzione \func{lockf}}
+\label{sec:file_lockf}
+
+Abbiamo visto come l'interfaccia POSIX per il \textit{file locking} sia molto
+più potente e flessibile di quella di BSD, questo comporta anche una maggiore
+complessità per via delle varie opzioni da passare a \func{fcntl}. Per questo
+motivo è disponibile anche una interfaccia semplificata (ripresa da System V)
+che utilizza la funzione \funcd{lockf}, il cui prototipo è:
+\begin{prototype}{sys/file.h}{int lockf(int fd, int cmd, off\_t len)}
+
+ Applica, controlla o rimuove un \textit{file lock} sul file \param{fd}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EWOULDBLOCK}] non è possibile acquisire il lock, e si è
+ selezionato \const{LOCK\_NB}, oppure l'operazione è proibita perché il
+ file è mappato in memoria.
+ \item[\errcode{ENOLCK}] il sistema non ha le risorse per il blocco: ci
+ sono troppi segmenti di \textit{lock} aperti, si è esaurita la tabella
+ dei \textit{file lock}.
+ \end{errlist}
+ ed inoltre \errval{EBADF}, \errval{EINVAL}.
+ }
+\end{prototype}
+
+Il comportamento della funzione dipende dal valore dell'argomento \param{cmd},
+che specifica quale azione eseguire; i valori possibili sono riportati in
+tab.~\ref{tab:file_lockf_type}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{7cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{LOCK\_SH}& Richiede uno \textit{shared lock}. Più processi possono
+ mantenere un blocco condiviso sullo stesso file.\\
+ \const{LOCK\_EX}& Richiede un \textit{exclusive lock}. Un solo processo
+ alla volta può mantenere un blocco esclusivo su un file.\\
+ \const{LOCK\_UN}& Sblocca il file.\\
+ \const{LOCK\_NB}& Non blocca la funzione quando il blocco non è disponibile,
+ si specifica sempre insieme ad una delle altre operazioni
+ con un OR aritmetico dei valori.\\
+ \hline
+ \end{tabular}
+ \caption{Valori possibili per l'argomento \param{cmd} di \func{lockf}.}
+ \label{tab:file_lockf_type}
+\end{table}
+
+Qualora il blocco non possa essere acquisito, a meno di non aver specificato
+\const{LOCK\_NB}, la funzione si blocca fino alla disponibilità dello stesso.
+Dato che la funzione è implementata utilizzando \func{fcntl} la semantica
+delle operazioni è la stessa di quest'ultima (pertanto la funzione non è
+affatto equivalente a \func{flock}).
+
+
+
+\subsection{Il \textit{mandatory locking}}
+\label{sec:file_mand_locking}
+
+\itindbeg{mandatory~locking}
+
+Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVr4,
+per introdurre un \textit{file locking} che, come dice il nome, fosse
+effettivo indipendentemente dai controlli eseguiti da un processo. Con il
+\textit{mandatory locking} infatti è possibile far eseguire il blocco del file
+direttamente al sistema, così che, anche qualora non si predisponessero le
+opportune verifiche nei processi, questo verrebbe comunque rispettato.
+
+Per poter utilizzare il \textit{mandatory locking} è stato introdotto un
+utilizzo particolare del bit \itindex{sgid~bit} \acr{sgid}. Se si ricorda
+quanto esposto in sez.~\ref{sec:file_special_perm}), esso viene di norma
+utilizzato per cambiare il \ids{GID} effettivo con cui viene eseguito un
+programma, ed è pertanto sempre associato alla presenza del permesso di
+esecuzione per il gruppo. Impostando questo bit su un file senza permesso di
+esecuzione in un sistema che supporta il \textit{mandatory locking}, fa sì che
+quest'ultimo venga attivato per il file in questione. In questo modo una
+combinazione dei permessi originariamente non contemplata, in quanto senza
+significato, diventa l'indicazione della presenza o meno del \textit{mandatory
+ locking}.\footnote{un lettore attento potrebbe ricordare quanto detto in
+ sez.~\ref{sec:file_perm_management} e cioè che il bit \acr{sgid} viene
+ cancellato (come misura di sicurezza) quando di scrive su un file, questo
+ non vale quando esso viene utilizzato per attivare il \textit{mandatory
+ locking}.}
+
+L'uso del \textit{mandatory locking} presenta vari aspetti delicati, dato che
+neanche l'amministratore può passare sopra ad un \textit{file lock}; pertanto
+un processo che blocchi un file cruciale può renderlo completamente
+inaccessibile, rendendo completamente inutilizzabile il sistema\footnote{il
+ problema si potrebbe risolvere rimuovendo il bit \itindex{sgid~bit}
+ \acr{sgid}, ma non è detto che sia così facile fare questa operazione con un
+ sistema bloccato.} inoltre con il \textit{mandatory locking} si può
+bloccare completamente un server NFS richiedendo una lettura su un file su cui
+è attivo un blocco. Per questo motivo l'abilitazione del \textit{mandatory
+ locking} è di norma disabilitata, e deve essere attivata filesystem per
+filesystem in fase di montaggio (specificando l'apposita opzione di
+\func{mount} riportata in sez.~\ref{sec:sys_file_config}), o con l'opzione
+\code{-o mand} per il comando omonimo).
+
+Si tenga presente inoltre che il \textit{mandatory locking} funziona solo
+sull'interfaccia POSIX di \func{fcntl}. Questo ha due conseguenze: che non si
+ha nessun effetto sui \textit{file lock} richiesti con l'interfaccia di
+\func{flock}, e che la granularità del blocco è quella del singolo byte, come
+per \func{fcntl}.
+
+La sintassi di acquisizione dei blocchi è esattamente la stessa vista in
+precedenza per \func{fcntl} e \func{lockf}, la differenza è che in caso di
+\textit{mandatory lock} attivato non è più necessario controllare la
+disponibilità di accesso al file, ma si potranno usare direttamente le
+ordinarie funzioni di lettura e scrittura e sarà compito del kernel gestire
+direttamente il \textit{file locking}.
+
+Questo significa che in caso di \textit{read lock} la lettura dal file potrà
+avvenire normalmente con \func{read}, mentre una \func{write} si bloccherà
+fino al rilascio del blocco, a meno di non aver aperto il file con
+\const{O\_NONBLOCK}, nel qual caso essa ritornerà immediatamente con un errore
+di \errcode{EAGAIN}.
+
+Se invece si è acquisito un \textit{write lock} tutti i tentativi di leggere o
+scrivere sulla regione del file bloccata fermeranno il processo fino al
+rilascio del blocco, a meno che il file non sia stato aperto con
+\const{O\_NONBLOCK}, nel qual caso di nuovo si otterrà un ritorno immediato
+con l'errore di \errcode{EAGAIN}.
+
+Infine occorre ricordare che le funzioni di lettura e scrittura non sono le
+sole ad operare sui contenuti di un file, e che sia \func{creat} che
+\func{open} (quando chiamata con \const{O\_TRUNC}) effettuano dei cambiamenti,
+così come \func{truncate}, riducendone le dimensioni (a zero nei primi due
+casi, a quanto specificato nel secondo). Queste operazioni sono assimilate a
+degli accessi in scrittura e pertanto non potranno essere eseguite (fallendo
+con un errore di \errcode{EAGAIN}) su un file su cui sia presente un qualunque
+blocco (le prime due sempre, la terza solo nel caso che la riduzione delle
+dimensioni del file vada a sovrapporsi ad una regione bloccata).
+
+L'ultimo aspetto della interazione del \textit{mandatory locking} con le
+funzioni di accesso ai file è quello relativo ai file mappati in memoria (che
+abbiamo trattato in sez.~\ref{sec:file_memory_map}); anche in tal caso
+infatti, quando si esegue la mappatura con l'opzione \const{MAP\_SHARED}, si
+ha un accesso al contenuto del file. Lo standard SVID prevede che sia
+impossibile eseguire il memory mapping di un file su cui sono presenti dei
+blocchi\footnote{alcuni sistemi, come HP-UX, sono ancora più restrittivi e lo
+ impediscono anche in caso di \textit{advisory locking}, anche se questo
+ comportamento non ha molto senso, dato che comunque qualunque accesso
+ diretto al file è consentito.} in Linux è stata però fatta la scelta
+implementativa\footnote{per i dettagli si possono leggere le note relative
+ all'implementazione, mantenute insieme ai sorgenti del kernel nel file
+ \file{Documentation/mandatory.txt}.} di seguire questo comportamento
+soltanto quando si chiama \func{mmap} con l'opzione \const{MAP\_SHARED} (nel
+qual caso la funzione fallisce con il solito \errcode{EAGAIN}) che comporta la
+possibilità di modificare il file.
+
+\itindend{file~locking}
+
+\itindend{mandatory~locking}
+
+
+\section{L'\textit{I/O multiplexing}}
+\label{sec:file_multiplexing}
+
+
+Uno dei problemi che si presentano quando si deve operare contemporaneamente
+su molti file usando le funzioni illustrate in
+cap.~\ref{cha:file_unix_interface} e cap.~\ref{cha:files_std_interface} è che
+si può essere bloccati nelle operazioni su un file mentre un altro potrebbe
+essere disponibile. L'\textit{I/O multiplexing} nasce risposta a questo
+problema. In questa sezione forniremo una introduzione a questa problematica
+ed analizzeremo le varie funzioni usate per implementare questa modalità di
+I/O.
+
+
+\subsection{La problematica dell'\textit{I/O multiplexing}}
+\label{sec:file_noblocking}
+
+Abbiamo visto in sez.~\ref{sec:sig_gen_beha}, affrontando la suddivisione fra
+\textit{fast} e \textit{slow} system call,\index{system~call~lente} che in
+certi casi le funzioni di I/O possono bloccarsi indefinitamente.\footnote{si
+ ricordi però che questo può accadere solo per le pipe, i socket ed alcuni
+ file di dispositivo\index{file!di~dispositivo}; sui file normali le funzioni
+ di lettura e scrittura ritornano sempre subito.} Ad esempio le operazioni
+di lettura possono bloccarsi quando non ci sono dati disponibili sul
+descrittore su cui si sta operando.
+
+Questo comportamento causa uno dei problemi più comuni che ci si trova ad
+affrontare nelle operazioni di I/O, che si verifica quando si deve operare con
+più file descriptor eseguendo funzioni che possono bloccarsi senza che sia
+possibile prevedere quando questo può avvenire (il caso più classico è quello
+di un server in attesa di dati in ingresso da vari client). Quello che può
+accadere è di restare bloccati nell'eseguire una operazione su un file
+descriptor che non è ``\textsl{pronto}'', quando ce ne potrebbe essere un
+altro disponibile. 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 della 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} 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 input/output
+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 system call che nella gran parte dei casi
+falliranno.
+
+Per superare questo problema è stato introdotto il concetto di \textit{I/O
+ multiplexing}, una nuova modalità di operazioni che consente di tenere sotto
+controllo più file descriptor in contemporanea, permettendo di bloccare un
+processo quando le operazioni volute non sono possibili, e di riprenderne
+l'esecuzione una volta che almeno una di quelle richieste sia effettuabile, in
+modo da poterla eseguire con la sicurezza di non restare bloccati.
+
+Dato che, come abbiamo già accennato, per i normali file su disco non si ha
+mai un accesso bloccante, l'uso più comune delle funzioni che esamineremo nei
+prossimi paragrafi è per i server di rete, in cui esse vengono utilizzate per
+tenere sotto controllo dei socket; pertanto ritorneremo su di esse con
+ulteriori dettagli e qualche esempio 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,\footnote{la funzione \func{select} è apparsa in
+ BSD4.2 e standardizzata in BSD4.4, ma è stata portata su tutti i sistemi che
+ supportano i socket, compreso le varianti di System V.} con la funzione
+\funcd{select}, il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/time.h}
+ \headdecl{sys/types.h}
+ \headdecl{unistd.h}
+ \funcdecl{int select(int ndfs, fd\_set *readfds, fd\_set *writefds, fd\_set
+ *exceptfds, struct timeval *timeout)}
+
+ Attende che uno dei file descriptor degli insiemi specificati diventi
+ attivo.
+
+ \bodydesc{La funzione in caso di successo restituisce il numero di file
+ descriptor (anche nullo) che sono attivi, e -1 in caso di 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}.
+}
+\end{functions}
+
+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:
+\begin{functions}
+ \headdecl{sys/time.h}
+ \headdecl{sys/types.h}
+ \headdecl{unistd.h}
+ \funcdecl{void \macro{FD\_ZERO}(fd\_set *set)}
+ Inizializza l'insieme (vuoto).
+
+ \funcdecl{void \macro{FD\_SET}(int fd, fd\_set *set)}
+ Inserisce il file descriptor \param{fd} nell'insieme.
+
+ \funcdecl{void \macro{FD\_CLR}(int fd, fd\_set *set)}
+ Rimuove il file descriptor \param{fd} dall'insieme.
+
+ \funcdecl{int \macro{FD\_ISSET}(int fd, fd\_set *set)}
+ Controlla se il file descriptor \param{fd} è nell'insieme.
+\end{functions}
+
+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\footnote{ad esempio in Linux,
+ fino alla serie 2.0.x, c'era un limite di 256 file per processo.}, ma da
+quando, come nelle versioni più recenti del kernel, questo limite è stato
+rimosso, esso indica le dimensioni massime dei numeri usati nei \textit{file
+ descriptor set}.\footnote{il suo valore, secondo lo standard POSIX
+ 1003.1-2001, è definito in \file{sys/select.h}, ed è pari a 1024.}
+
+Si tenga presente che i \textit{file descriptor set} devono sempre essere
+inizializzati con \macro{FD\_ZERO}; passare a \func{select} un valore non
+inizializzato può dar luogo a comportamenti non prevedibili; 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}; inoltre con Linux
+ possono verificarsi casi particolari, ad esempio quando arrivano dati su un
+ socket dalla rete che poi risultano corrotti e vengono scartati, può
+ accadere che \func{select} riporti il relativo file descriptor come
+ leggibile, ma una successiva \func{read} si blocchi.} il secondo,
+\param{writefds}, per verificare la possibilità 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.\footnote{si ricordi che
+ i file descriptor sono numerati progressivamente a partire da zero, ed il
+ valore indica il numero più alto fra quelli da tenere sotto controllo;
+ dimenticarsi di aumentare di uno il valore di \param{ndfs} è un errore
+ comune.}
+
+Infine l'argomento \param{timeout}, espresso con 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.
+
+La funzione restituisce il numero di file descriptor pronti,\footnote{questo è
+ il comportamento previsto dallo standard, ma la standardizzazione della
+ funzione è recente, ed esistono ancora alcune versioni di Unix che non si
+ comportano in questo modo.} 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 si
+ha un timeout viene restituito un valore nullo e gli insiemi non vengono
+modificati. In caso di errore la funzione restituisce -1, ed i valori dei tre
+insiemi sono indefiniti e non si può fare nessun affidamento sul loro
+contenuto.
+
+\itindend{file~descriptor~set}
+
+Una volta ritornata la funzione si potrà controllare quali sono i file
+descriptor pronti ed operare su di essi, si tenga presente però che si tratta
+solo di un suggerimento, esistono infatti condizioni\footnote{ad esempio
+ quando su un socket arrivano dei dati che poi vengono scartati perché
+ corrotti.} in cui \func{select} può riportare in maniera spuria che un file
+descriptor è pronto in lettura, quando una successiva lettura si bloccherebbe.
+Per questo quando si usa \textit{I/O multiplexing} è sempre raccomandato l'uso
+delle funzioni di lettura e scrittura in modalità non bloccante.
+
+In Linux \func{select} modifica anche il valore di \param{timeout},
+impostandolo al tempo restante, quando la funzione viene interrotta da un
+segnale. In tal caso infatti si ha un errore di \errcode{EINTR}, ed occorre
+rilanciare la funzione; 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.\footnote{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.}
+
+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 \file{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 \file{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{prototype}{sys/select.h}
+ {int pselect(int n, fd\_set *readfds, fd\_set *writefds, fd\_set *exceptfds,
+ struct timespec *timeout, sigset\_t *sigmask)}
+
+ Attende che uno dei file descriptor degli insiemi specificati diventi
+ attivo.
+
+ \bodydesc{La funzione in caso di successo restituisce il numero di file
+ descriptor (anche nullo) che sono attivi, e -1 in caso di 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}.}
+\end{prototype}
+
+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.\footnote{in realtà la system call di Linux aggiorna il
+ valore al tempo rimanente, ma la funzione fornita dalle \acr{glibc} modifica
+ questo comportamento passando alla 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.} Inoltre prende un argomento aggiuntivo
+\param{sigmask} che è il puntatore ad una maschera di segnali (si veda
+sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa
+immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della
+funzione.
+
+L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
+\textit{race condition} \itindex{race~condition} quando ci si deve porre in
+attesa sia di un segnale che di dati. La tecnica classica è quella di
+utilizzare il gestore per impostare una \index{variabili!globali} variabile
+globale e controllare questa nel corpo principale del programma; abbiamo visto
+in sez.~\ref{sec:sig_example} 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 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 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 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 un'altra
+interfaccia, basata sulla funzione \funcd{poll},\footnote{la funzione è
+ prevista dallo standard XPG4, ed è stata introdotta in Linux come system
+ call a partire dal kernel 2.1.23 ed inserita nelle \acr{libc} 5.4.28.} il
+cui prototipo è:
+\begin{prototype}{sys/poll.h}
+ {int poll(struct pollfd *ufds, unsigned int nfds, int timeout)}
+
+ La funzione attende un cambiamento di stato su un insieme di file
+ descriptor.
+
+ \bodydesc{La funzione restituisce il numero di file descriptor con attività
+ in caso di successo, o 0 se c'è stato un timeout e -1 in caso di errore,
+ ed in quest'ultimo 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}.}
+\end{prototype}
+
+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}).
+
+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}. 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.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{\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}
+
+Le costanti che definiscono i valori relativi ai bit usati nelle maschere
+binarie dei campi \var{events} e \var{revents} sono riportati in
+tab.~\ref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono
+suddivise in tre gruppi, nel primo gruppo si sono indicati i bit utilizzati
+per controllare l'attività in ingresso, nel secondo quelli per l'attività in
+uscita, mentre 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 SysV che usa gli
+\textit{stream};\footnote{essi sono una interfaccia specifica di SysV non
+ presente in Linux, e non hanno nulla a che fare con i file \textit{stream}
+ delle librerie standard del C.} è da questi che derivano i nomi di alcune
+costanti, in quanto per essi 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.
+
+Si tenga conto comunque che le costanti relative ai diversi tipi di dati
+normali e prioritari, vale a dire \const{POLLRDNORM}, \const{POLLWRNORM},
+\const{POLLRDBAND} e \const{POLLWRBAND} fanno riferimento alle implementazioni
+in stile SysV (in particolare le ultime due non vengono usate su Linux), e
+sono utilizzabili soltanto qualora si sia definita la macro
+\macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in testa al
+ file, definirla soltanto prima di includere \file{sys/poll.h} non è
+ sufficiente.}
+
+In caso di successo funzione 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, nel qual caso vengono utilizzati i
+valori di tab.~\ref{tab:file_pollfd_flags} esclusivi di \var{revents}. Un
+valore 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.\footnote{anche se usando dei bit un \textit{file descriptor
+ set} può essere più efficiente di un vettore di strutture \struct{pollfd},
+ qualora si debba osservare un solo file descriptor con un valore molto alto
+ ci si troverà ad utilizzare inutilmente un maggiore quantitativo di
+ memoria.}
+
+Inoltre con \func{select} lo stesso \itindex{file~descriptor~set} \textit{file
+ descriptor set} è usato sia in ingresso che in uscita, e questo significa
+che tutte le volte che si vuole ripetere l'operazione occorre reinizializzarlo
+da capo. Questa operazione, che può essere molto onerosa se i file descriptor
+da tenere sotto osservazione sono molti, non è invece necessaria con
+\func{poll}.
+
+Abbiamo visto in sez.~\ref{sec:file_select} come lo standard POSIX preveda una
+variante di \func{select} che consente di gestire correttamente la ricezione
+dei segnali nell'attesa su un file descriptor. Con l'introduzione di una
+implementazione reale di \func{pselect} nel kernel 2.6.16, è stata aggiunta
+anche una analoga funzione che svolga lo stesso ruolo per \func{poll}.
+
+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{prototype}{sys/poll.h}
+ {int ppoll(struct pollfd *fds, nfds\_t nfds, const struct timespec *timeout,
+ const sigset\_t *sigmask)}
+
+ La funzione attende un cambiamento di stato su un insieme di file
+ descriptor.
+
+ \bodydesc{La funzione restituisce il numero di file descriptor con attività
+ in caso di successo, o 0 se c'è stato un timeout e -1 in caso di errore,
+ ed in quest'ultimo 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}.}
+\end{prototype}
+
+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 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}.\footnote{anche
+ se in questo caso non esiste nessuno standard che richiede questo
+ comportamento.}
+
+
+\subsection{L'interfaccia di \textit{epoll}}
+\label{sec:file_epoll}
+
+\itindbeg{epoll}
+
+Nonostante \func{poll} presenti alcuni vantaggi rispetto a \func{select},
+anche questa funzione non è molto efficiente quando deve essere utilizzata con
+un gran numero di file descriptor,\footnote{in casi del genere \func{select}
+ viene scartata a priori, perché può avvenire che il numero di file
+ descriptor ecceda le dimensioni massime di un \itindex{file~descriptor~set}
+ \textit{file descriptor set}.} in particolare nel caso in cui solo pochi di
+questi diventano attivi. Il problema in questo caso è che il tempo impiegato
+da \func{poll} a trasferire i dati da e verso il kernel è proporzionale al
+numero di file descriptor osservati, non a quelli che presentano attività.
+
+Quando ci sono decine di migliaia di file descriptor osservati e migliaia di
+eventi al secondo,\footnote{il caso classico è quello di un server web di un
+ sito con molti accessi.} l'uso di \func{poll} comporta la necessità di
+trasferire avanti ed indietro da user space a kernel space la lunga lista
+delle strutture \struct{pollfd} migliaia di volte al secondo. A questo poi si
+aggiunge il fatto che la maggior parte del tempo di esecuzione sarà impegnato
+ad eseguire una scansione su tutti i file descriptor tenuti sotto controllo
+per determinare quali di essi (in genere una piccola percentuale) sono
+diventati attivi. In una situazione come questa l'uso delle funzioni classiche
+dell'interfaccia dell'\textit{I/O multiplexing} viene a costituire un collo di
+bottiglia che degrada irrimediabilmente le prestazioni.
+
+Per risolvere questo tipo di situazioni sono state ideate delle interfacce
+specialistiche\footnote{come \texttt{/dev/poll} in Solaris, o \texttt{kqueue}
+ in BSD.} il cui scopo fondamentale è quello di restituire solamente le
+informazioni relative ai file descriptor osservati che presentano una
+attività, evitando così le problematiche appena illustrate. In genere queste
+prevedono che si registrino una sola volta i file descriptor da tenere sotto
+osservazione, e forniscono un meccanismo che notifica quali di questi
+presentano attività.
+
+Le modalità con cui avviene la notifica sono due, la prima è quella classica
+(quella usata da \func{poll} e \func{select}) che viene chiamata \textit{level
+ triggered}.\footnote{la nomenclatura è stata introdotta da Jonathan Lemon in
+ un articolo su \texttt{kqueue} al BSDCON 2000, e deriva da quella usata
+ nell'elettronica digitale.} In questa modalità vengono notificati i file
+descriptor che sono \textsl{pronti} per l'operazione richiesta, e questo
+avviene indipendentemente dalle operazioni che possono essere state fatte su
+di essi a partire dalla precedente notifica. Per chiarire meglio il concetto
+ricorriamo ad un esempio: se su un file descriptor sono diventati disponibili
+in lettura 2000 byte ma dopo la notifica ne sono letti solo 1000 (ed è quindi
+possibile eseguire una ulteriore lettura dei restanti 1000), in modalità
+\textit{level triggered} questo sarà nuovamente notificato come
+\textsl{pronto}.
+
+La seconda modalità, è detta \textit{edge triggered}, e prevede che invece
+vengano notificati solo i file descriptor che hanno subito una transizione da
+\textsl{non pronti} a \textsl{pronti}. Questo significa che in modalità
+\textit{edge triggered} nel caso del precedente esempio il file descriptor
+diventato pronto da cui si sono letti solo 1000 byte non verrà nuovamente
+notificato come pronto, nonostante siano ancora disponibili in lettura 1000
+byte. Solo una volta che si saranno esauriti tutti i 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 è \textit{epoll},\footnote{l'interfaccia è stata creata da Davide
+ Libenzi, ed è stata introdotta per la prima volta nel kernel 2.5.44, ma la
+ sua forma definitiva è stata raggiunta nel kernel 2.5.66.} anche se sono in
+discussione altre interfacce con le quali si potranno effettuare lo stesso
+tipo di operazioni;\footnote{al momento della stesura di queste note (Giugno
+ 2007) un'altra interfaccia proposta è quella di \textit{kevent}, che
+ fornisce un sistema di notifica di eventi generico in grado di fornire le
+ stesse funzionalità di \textit{epoll}, esiste però una forte discussione
+ intorno a tutto ciò e niente di definito.} \textit{epoll} è in grado di
+operare sia in modalità \textit{level triggered} che \textit{edge triggered}.
+
+La prima versione \textit{epoll} prevedeva l'apertura di uno speciale file di
+dispositivo, \texttt{/dev/epoll}, per ottenere un file descriptor da
+utilizzare con le funzioni dell'interfaccia,\footnote{il backporting
+ dell'interfaccia per il kernel 2.4, non ufficiale, utilizza sempre questo
+ file.} ma poi si è passati all'uso di apposite \textit{system call}. Il
+primo passo per usare l'interfaccia di \textit{epoll} è pertanto quello
+ottenere detto file descriptor chiamando una delle funzioni
+\funcd{epoll\_create} e \funcd{epoll\_create1},\footnote{l'interfaccia di
+ \textit{epoll} è stata inserita nel kernel a partire dalla versione 2.5.44,
+ ed il supporto è stato aggiunto alle \acr{glibc} 2.3.2.} i cui prototipi
+sono:
+\begin{functions}
+ \headdecl{sys/epoll.h}
+
+ \funcdecl{int epoll\_create(int size)}
+ \funcdecl{int epoll\_create1(int flags)}
+
+ Apre un file descriptor per \textit{epoll}.
+
+ \bodydesc{Le funzioni restituiscono un file descriptor per \textit{epoll} in
+ caso di successo, o $-1$ in caso di errore, nel qual caso \var{errno}
+ assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] si è specificato un valore di \param{size} non
+ positivo o non valido per \param{flags}.
+ \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
+ nel sistema.
+ \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{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
+ l'istanza.
+ \end{errlist}
+}
+\end{functions}
+
+Entrambe le funzioni restituiscono un file descriptor speciale,\footnote{esso
+ non è associato a nessun file su disco, inoltre a differenza dei normali
+ file descriptor non può essere inviato ad un altro processo attraverso un
+ socket locale (vedi sez.~\ref{sec:sock_fd_passing}).} detto anche
+\textit{epoll descriptor}, che viene associato alla infrastruttura utilizzata
+dal kernel per gestire la notifica degli eventi. 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.\footnote{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\footnote{è disponibile solo a partire dal kernel 2.6.27.} come
+estensione della precedente, 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 veda il significato di
+\const{O\_CLOEXEC} in tab.~\ref{tab:file_open_flags}), 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 dell'interfaccia,
+\funcd{epoll\_ctl}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+ {int epoll\_ctl(int epfd, int op, int fd, struct epoll\_event *event)}
+
+ Esegue le operazioni di controllo di \textit{epoll}.
+
+ \bodydesc{La funzione restituisce $0$ in caso di successo o $-1$ in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il file descriptor \param{epfd} o \param{fd} non sono
+ validi.
+ \item[\errcode{EEXIST}] l'operazione richiesta è \const{EPOLL\_CTL\_ADD} ma
+ \param{fd} è già stato inserito in \param{epfd}.
+ \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+ con \func{epoll\_create}, o \param{fd} è lo stesso \param{epfd} o
+ l'operazione richiesta con \param{op} non è supportata.
+ \item[\errcode{ENOENT}] l'operazione richiesta è \const{EPOLL\_CTL\_MOD} o
+ \const{EPOLL\_CTL\_DEL} ma \param{fd} non è inserito in \param{epfd}.
+ \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel gestire
+ l'operazione richiesta.
+ \item[\errcode{EPERM}] il file \param{fd} non supporta \textit{epoll}.
+ \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}.
+ \end{errlist}
+}
+\end{prototype}
+
+Il comportamento della funzione viene controllato dal valore dall'argomento
+\param{op} che consente di specificare quale operazione deve essere eseguita.
+Le costanti che definiscono i valori utilizzabili per \param{op}
+sono riportate in tab.~\ref{tab:epoll_ctl_operation}, assieme al significato
+delle operazioni cui fanno riferimento.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{EPOLL\_CTL\_ADD}& Aggiunge un nuovo file descriptor da osservare
+ \param{fd} alla lista dei file descriptor
+ controllati tramite \param{epfd}, in
+ \param{event} devono essere specificate le
+ modalità di osservazione.\\
+ \const{EPOLL\_CTL\_MOD}& Modifica le modalità di osservazione del file
+ descriptor \param{fd} secondo il contenuto di
+ \param{event}.\\
+ \const{EPOLL\_CTL\_DEL}& Rimuove il file descriptor \param{fd} dalla lista
+ dei file controllati tramite \param{epfd}.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{op} che consentono di scegliere quale
+ operazione di controllo effettuare con la funzione \func{epoll\_ctl}.}
+ \label{tab:epoll_ctl_operation}
+\end{table}
+
+La funzione prende sempre come primo argomento un file descriptor di
+\textit{epoll}, \param{epfd}, che deve essere stato ottenuto in precedenza con
+una chiamata a \func{epoll\_create}. L'argomento \param{fd} indica invece il
+file descriptor che si vuole tenere sotto controllo, quest'ultimo può essere
+un qualunque file descriptor utilizzabile con \func{poll}, ed anche un altro
+file descriptor di \textit{epoll}, ma non lo stesso \param{epfd}.
+
+L'ultimo argomento, \param{event}, deve essere un puntatore ad una struttura
+di tipo \struct{epoll\_event}, ed ha significato solo con le operazioni
+\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD}, per le quali serve ad
+indicare quale tipo di evento relativo ad \param{fd} si vuole che sia tenuto
+sotto controllo. L'argomento viene ignorato con l'operazione
+\const{EPOLL\_CTL\_DEL}.\footnote{fino al kernel 2.6.9 era comunque richiesto
+ che questo fosse un puntatore valido, anche se poi veniva ignorato; a
+ partire dal 2.6.9 si può specificare anche 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]{\textwidth}
+ \includestruct{listati/epoll_event.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{epoll\_event}, che consente di specificare
+ gli eventi associati ad un file descriptor controllato con
+ \textit{epoll}.}
+ \label{fig:epoll_event}
+\end{figure}
+
+La struttura \struct{epoll\_event} è l'analoga di \struct{pollfd} e come
+quest'ultima serve sia in ingresso (quando usata con \func{epoll\_ctl}) ad
+impostare quali eventi osservare, che in uscita (nei risultati ottenuti con
+\func{epoll\_wait}) per ricevere le notifiche degli eventi avvenuti. La sua
+definizione è riportata in fig.~\ref{fig:epoll_event}.
+
+Il primo campo, \var{events}, è una maschera binaria in cui ciascun bit
+corrisponde o ad un tipo di evento, o una modalità di notifica; detto campo
+deve essere specificato come OR aritmetico delle costanti riportate in
+tab.~\ref{tab:epoll_events}. Il secondo campo, \var{data}, è una \direct{union}
+che serve a identificare il file descriptor a cui si intende fare riferimento,
+ed in astratto può contenere un valore qualsiasi (specificabile in diverse
+forme) che ne permetta una indicazione univoca. Il modo più comune di usarlo
+però è quello in cui si specifica il terzo argomento di \func{epoll\_ctl}
+nella forma \var{event.data.fd}, assegnando come valore di questo campo lo
+stesso valore dell'argomento \param{fd}, cosa che permette una immediata
+identificazione del file descriptor.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{EPOLLIN} & Il file è pronto per le operazioni di lettura
+ (analogo di \const{POLLIN}).\\
+ \const{EPOLLOUT} & Il file è pronto per le operazioni di scrittura
+ (analogo di \const{POLLOUT}).\\
+ \const{EPOLLRDHUP} & L'altro capo di un socket di tipo
+ \const{SOCK\_STREAM} (vedi sez.~\ref{sec:sock_type})
+ ha chiuso la connessione o il capo in scrittura
+ della stessa (vedi
+ sez.~\ref{sec:TCP_shutdown}).\footnotemark\\
+ \const{EPOLLPRI} & Ci sono \itindex{out-of-band} dati urgenti
+ disponibili in lettura (analogo di
+ \const{POLLPRI}); questa condizione viene comunque
+ riportata in uscita, e non è necessaria impostarla
+ in ingresso.\\
+ \const{EPOLLERR} & Si è verificata una condizione di errore
+ (analogo di \const{POLLERR}); questa condizione
+ viene comunque riportata in uscita, e non è
+ necessaria impostarla in ingresso.\\
+ \const{EPOLLHUP} & Si è verificata una condizione di hung-up; questa
+ condizione viene comunque riportata in uscita, e non
+ è necessaria impostarla in ingresso.\\
+ \const{EPOLLET} & Imposta la notifica in modalità \textit{edge
+ triggered} per il file descriptor associato.\\
+ \const{EPOLLONESHOT}& Imposta la modalità \textit{one-shot} per il file
+ descriptor associato.\footnotemark\\
+ \hline
+ \end{tabular}
+ \caption{Costanti che identificano i bit del campo \param{events} di
+ \struct{epoll\_event}.}
+ \label{tab:epoll_events}
+\end{table}
+
+\footnotetext{questa modalità è disponibile solo a partire dal kernel 2.6.17,
+ ed è utile per riconoscere la chiusura di una connessione dall'altro capo
+ quando si lavora in modalità \textit{edge triggered}.}
+
+\footnotetext[48]{questa modalità è disponibile solo a partire dal kernel
+ 2.6.2.}
+
+Le modalità di utilizzo di \textit{epoll} prevedono che si definisca qual'è
+l'insieme dei file descriptor da tenere sotto controllo tramite un certo
+\textit{epoll descriptor} \param{epfd} attraverso una serie di chiamate a
+\const{EPOLL\_CTL\_ADD}.\footnote{un difetto dell'interfaccia è che queste
+ chiamate devono essere ripetute per ciascun file descriptor, incorrendo in
+ una perdita di prestazioni qualora il numero di file descriptor sia molto
+ grande; per questo è stato proposto di introdurre come estensione una
+ funzione \func{epoll\_ctlv} che consenta di effettuare con una sola chiamata
+ le impostazioni per un blocco di file descriptor.} L'uso di
+\const{EPOLL\_CTL\_MOD} consente in seguito di modificare le modalità di
+osservazione di un file descriptor che sia già stato aggiunto alla lista di
+osservazione.
+
+Le impostazioni di default prevedono che la notifica degli eventi richiesti
+sia effettuata in modalità \textit{level triggered}, a meno che sul file
+descriptor non si sia impostata la modalità \textit{edge triggered},
+registrandolo con \const{EPOLLET} attivo nel campo \var{events}. Si tenga
+presente che è possibile tenere sotto osservazione uno stesso file descriptor
+su due \textit{epoll descriptor} diversi, ed entrambi riceveranno le
+notifiche, anche se questa pratica è sconsigliata.
+
+Qualora non si abbia più interesse nell'osservazione di un file descriptor lo
+si può rimuovere dalla lista associata a \param{epfd} con
+\const{EPOLL\_CTL\_DEL}; si tenga conto inoltre che i file descriptor sotto
+osservazione che vengono chiusi sono eliminati dalla lista automaticamente e
+non è necessario usare \const{EPOLL\_CTL\_DEL}.
+
+Infine una particolare modalità di notifica è quella impostata con
+\const{EPOLLONESHOT}: a causa dell'implementazione di \textit{epoll} infatti
+quando si è in modalità \textit{edge triggered} l'arrivo in rapida successione
+di dati in blocchi separati\footnote{questo è tipico con i socket di rete, in
+ quanto i dati arrivano a pacchetti.} può causare una generazione di eventi
+(ad esempio segnalazioni di dati in lettura disponibili) anche se la
+condizione è già stata rilevata.\footnote{si avrebbe cioè una rottura della
+ logica \textit{edge triggered}.}
+
+Anche se la situazione è facile da gestire, la si può evitare utilizzando
+\const{EPOLLONESHOT} per impostare la modalità \textit{one-shot}, in cui la
+notifica di un evento viene effettuata una sola volta, dopo di che il file
+descriptor osservato, pur restando nella lista di osservazione, viene
+automaticamente disattivato,\footnote{la cosa avviene contestualmente al
+ ritorno di \func{epoll\_wait} a causa dell'evento in questione.} e per
+essere riutilizzato dovrà essere riabilitato esplicitamente con una successiva
+chiamata con \const{EPOLL\_CTL\_MOD}.
+
+Una volta impostato l'insieme di file descriptor che si vogliono osservare con
+i relativi eventi, la funzione che consente di attendere l'occorrenza di uno
+di tali eventi è \funcd{epoll\_wait}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+ {int epoll\_wait(int epfd, struct epoll\_event * events, int maxevents, int
+ timeout)}
+
+ Attende che uno dei file descriptor osservati sia pronto.
+
+ \bodydesc{La funzione restituisce il numero di file descriptor pronti in
+ caso di successo o $-1$ in caso di errore, nel qual caso \var{errno}
+ assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] il file descriptor \param{epfd} non è valido.
+ \item[\errcode{EFAULT}] il puntatore \param{events} non è valido.
+ \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
+ della scadenza di \param{timeout}.
+ \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+ con \func{epoll\_create}, o \param{maxevents} non è maggiore di zero.
+ \end{errlist}
+}
+\end{prototype}
+
+La funzione si blocca in attesa di un evento per i file descriptor registrati
+nella lista di osservazione di \param{epfd} fino ad un tempo massimo
+specificato in millisecondi tramite l'argomento \param{timeout}. Gli eventi
+registrati vengono riportati in un vettore di strutture \struct{epoll\_event}
+(che deve essere stato allocato in precedenza) all'indirizzo indicato
+dall'argomento \param{events}, fino ad un numero massimo di eventi impostato
+con l'argomento \param{maxevents}.
+
+La funzione ritorna il numero di eventi rilevati, o un valore nullo qualora
+sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo,
+oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che
+indica di non attendere e ritornare immediatamente,\footnote{anche in questo
+ caso il valore di ritorno sarà nullo.} o il valore $-1$, che indica
+un'attesa indefinita. L'argomento \param{maxevents} dovrà invece essere sempre
+un intero positivo.
+
+Come accennato la funzione restituisce i suoi risultati nel vettore di
+strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel
+campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli
+eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era
+stato impostato per il file descriptor per cui si è verificato l'evento quando
+questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
+\const{EPOLL\_CTL\_ADD}, in questo modo il campo \var{data} consente di
+identificare il file descriptor.\footnote{ed è per questo che, come accennato,
+ è consuetudine usare per \var{data} il valore del file descriptor stesso.}
+
+Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da
+come si è impostata la modalità di osservazione (se \textit{level triggered} o
+\textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura
+che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait}
+questi vengano combinati. Inoltre qualora su un file descriptor fossero
+presenti eventi non ancora notificati, e si effettuasse una modifica
+dell'osservazione con \const{EPOLL\_CTL\_MOD}, questi verrebbero riletti alla
+luce delle modifiche.
+
+Si tenga presente infine che con l'uso della modalità \textit{edge triggered}
+il ritorno di \func{epoll\_wait} indica che un file descriptor è pronto e
+resterà tale fintanto che non si sono completamente esaurite le operazioni su
+di esso. Questa condizione viene generalmente rilevata dall'occorrere di un
+errore di \errcode{EAGAIN} al ritorno di una \func{read} o una
+\func{write},\footnote{è opportuno ricordare ancora una volta che l'uso
+ dell'\textit{I/O multiplexing} richiede di operare sui file in modalità non
+ bloccante.} ma questa non è la sola modalità possibile, ad esempio la
+condizione può essere riconosciuta anche per il fatto che sono stati
+restituiti meno dati di quelli richiesti.
+
+Come già per \func{select} e \func{poll} anche per l'interfaccia di
+\textit{epoll} si pone il problema di gestire l'attesa di segnali e di dati
+contemporaneamente per le osservazioni fatte in sez.~\ref{sec:file_select},
+per fare questo di nuovo è necessaria una variante della funzione di attesa
+che consenta di reimpostare all'uscita una maschera di segnali, analoga alle
+estensioni \func{pselect} e \func{ppoll} che abbiamo visto in precedenza per
+\func{select} e \func{poll}; in questo caso la funzione si chiama
+\funcd{epoll\_pwait}\footnote{la funziona è 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{prototype}{sys/epoll.h}
+ {int epoll\_pwait(int epfd, struct epoll\_event * events, int maxevents,
+ int timeout, const sigset\_t *sigmask)}
+
+ Attende che uno dei file descriptor osservati sia pronto, mascherando i
+ segnali.
+
+ \bodydesc{La funzione restituisce il numero di file descriptor pronti in
+ caso di successo o $-1$ in caso di errore, nel qual caso \var{errno}
+ assumerà uno dei valori già visti con \funcd{epoll\_wait}.
+}
+\end{prototype}
+
+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'I/O multiplexing appena illustrate.
+
+In questo tipo di interfacce infatti ci si aspetta che il processo gestisca
+gli eventi a cui vuole rispondere 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}.\footnote{in sostanza se non
+ fossero per i segnali non ci sarebbe da doversi preoccupare, fintanto che si
+ effettuano operazioni all'interno di un processo, della non atomicità delle
+ \index{system~call~lente} 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.\footnote{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 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, \func{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{prototype}{sys/signalfd.h}
+ {int signalfd(int fd, const sigset\_t *mask, int flags)}
+
+ Crea o modifica un file descriptor per la ricezione dei segnali.
+
+ \bodydesc{La funzione restituisce un numero di file descriptor in caso di
+ successo o $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
+ dei valori:
+ \begin{errlist}
+ \item[\errcode{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{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file
+ descriptor di \func{signalfd}.
+ \item[\errcode{ENODEV}] il kernel non può montare internamente il
+ dispositivo per la gestione anonima degli inode associati al file
+ descriptor.
+ \end{errlist}
+ ed inoltre \errval{EMFILE} e \errval{ENFILE}.
+}
+\end{prototype}
+
+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}.\footnote{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).\footnote{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.\footnote{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]{\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.
+
+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
+fifo.
+
+\begin{figure}[!htbp]
+ \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 primo passo (\texttt{\small 19--20}) è la crezione 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}[!htbp]
+ \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 \texttt{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},\footnote{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 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.\footnote{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 \const{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.\footnote{si ricordi come
+ sia la 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 \const{signalfd\_siginfo} letta in \var{siginf}\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à.} ed il \textit{pid} del processo da cui lo ha ricevuto; inoltre
+(\texttt{\small 21--24}) si controllerà anche se il segnale ricevuto è
+\var{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 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 resituisce un errore di \errcode{EAGAIN}
+(\texttt{\small 29--35}).\footnote{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 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{Verbatim}
+piccardi@hain:~/gapil/sources$ ./a.out
+FifoReporter starting, pid 4568
+\end{Verbatim}
+%$
+e scrivendo qualcosa sull'altro terminale con:
+\begin{Verbatim}
+root@hain:~# echo prova > /tmp/reporter.fifo
+\end{Verbatim}
+si otterrà:
+\begin{Verbatim}
+Message from fifo:
+prova
+end message
+\end{Verbatim}
+mentre inviando un segnale:
+\begin{Verbatim}
+root@hain:~# kill 4568
+\end{Verbatim}
+si avrà:
+\begin{Verbatim}
+Signal received:
+Got SIGTERM
+From pid 3361
+\end{Verbatim}
+ed infine premendo \texttt{C-\bslash} sul terminale in cui è in esecuzione si
+vedrà:
+\begin{Verbatim}
+^\Signal received:
+Got SIGQUIT
+From pid 0
+\end{Verbatim}
+e si potrà far uscire il programma con \texttt{C-c} ottenendo:
+\begin{Verbatim}
+^CSignal received:
+Got SIGINT
+From pid 0
+SIGINT means exit
+\end{Verbatim}
+
+
+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.\footnote{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 prevista, quella che
+consente di creare un timer, è \funcd{timerfd\_create}, il cui prototipo è:
+\begin{prototype}{sys/timerfd.h}
+ {int timerfd\_create(int clockid, int flags)}
+
+ Crea un timer associato ad un file descriptor per la notifica.
+
+ \bodydesc{La funzione restituisce un numero di file descriptor in caso di
+ successo o $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
+ dei valori:
+ \begin{errlist}
+ \item[\errcode{EINVAL}] 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{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file
+ descriptor di \func{signalfd}.
+ \item[\errcode{ENODEV}] il kernel non può montare internamente il
+ dispositivo per la gestione anonima degli inode associati al file
+ descriptor.
+ \end{errlist}
+ ed inoltre \errval{EMFILE} e \errval{ENFILE}.
+}
+\end{prototype}
+
+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{esso è 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},\footnote{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.\footnote{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 la funzione omologa di
+\func{timer\_settime} per la nuova interfaccia; questa è
+\funcd{timerfd\_settime} ed il suo prototipo è:
+\begin{prototype}{sys/timerfd.h}
+ {int timerfd\_settime(int fd, int flags,
+ const struct itimerspec *new\_value,
+ struct itimerspec *old\_value)}
+
+ Crea un timer associato ad un file descriptor per la notifica.
+
+ \bodydesc{La funzione restituisce un numero di file descriptor in caso di
+ successo o $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
+ dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] l'argomento \param{fd} non corrisponde ad un file
+ descriptor.
+ \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.
+ \item[\errcode{EFAULT}] o \param{new\_value} o \param{old\_value} non sono
+ puntatori validi.
+ \end{errlist}
+}
+\end{prototype}
+
+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;\footnote{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}.\footnote{anche questo valore, che è l'analogo di
+ \const{TIMER\_ABSTIME} è l'unico attualmente possibile per \param{flags}.}
+
+L'ultima funzione prevista dalla nuova interfaccia è \funcd{timerfd\_gettime},
+che è l'analoga di \func{timer\_gettime}, il suo prototipo è:
+\begin{prototype}{sys/timerfd.h}
+ {int timerfd\_gettime(int fd, struct itimerspec *curr\_value)}
+
+ Crea un timer associato ad un file descriptor per la notifica.
+
+ \bodydesc{La funzione restituisce un numero di file descriptor in caso di
+ successo o $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
+ dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] l'argomento \param{fd} non corrisponde ad un file
+ descriptor.
+ \item[\errcode{EINVAL}] il file descriptor \param{fd} non è stato ottenuto
+ con \func{timerfd\_create}.
+ \item[\errcode{EFAULT}] o \param{curr\_value} non è un puntatore valido.
+ \end{errlist}
+}
+\end{prototype}