+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\index{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 \textit{deadlock}\itindex{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 \textit{polling}\itindex{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 consenta 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 disponibile, 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 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 \textit{socket}\index{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 n, 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{n} 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 \textsl{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} nell'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, non c'è più un limite
+massimo, 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.
+
+La funzione richiede di specificare tre insiemi distinti di file descriptor;
+il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
+effettuare una lettura,\footnote{per essere precisi la funzione ritornerà in
+ tutti i casi in cui la successiva esecuzione di \func{read} risulti non
+ bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo,
+\param{writefds}, per verificare la possibilità effettuare una scrittura ed il
+terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i
+messaggi urgenti su un \textit{socket}\index{socket}, vedi
+sez.~\ref{sec:TCP_urgent_data}).
+
+Dato che in genere non si tengono mai sotto controllo fino a
+\const{FD\_SETSIZE} file contemporaneamente la funzione richiede di
+specificare qual è il numero massimo dei file descriptor indicati nei tre
+insiemi precedenti. Questo viene fatto per efficienza, per evitare di passare
+e far controllare al kernel una quantità di memoria superiore a quella
+necessaria. Questo limite viene indicato tramite l'argomento \param{n}, che
+deve corrispondere al valore massimo aumentato di uno.\footnote{i file
+ descriptor infatti sono contati a partire da zero, ed il valore indica il
+ numero di quelli da tenere sotto controllo; dimenticarsi di aumentare di uno
+ il valore di \param{n} è un errore comune.} Infine l'argomento
+\param{timeout}, specifica un tempo massimo di attesa prima che la funzione
+ritorni; se impostato a \val{NULL} la funzione attende indefinitamente. Si può
+specificare anche un tempo nullo (cioè una struttura \struct{timeval} con i
+campi impostati a zero), qualora si voglia semplicemente controllare lo stato
+corrente dei file descriptor.
+\itindend{file~descriptor~set}
+
+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.
+
+In Linux \func{select} modifica anche il valore di \param{timeout},
+impostandolo al tempo restante in caso di interruzione prematura; questo è
+utile quando la funzione viene interrotta da un segnale, in tal caso infatti
+si ha un errore di \errcode{EINTR}, ed occorre rilanciare la funzione; in
+questo modo non è necessario ricalcolare tutte le volte il tempo
+rimanente.\footnote{questo può causare problemi di portabilità sia quando si
+ trasporta codice scritto su Linux che legge questo valore, sia quando si
+ usano programmi scritti per altri sistemi che non dispongono di questa
+ caratteristica e ricalcolano \param{timeout} tutte le volte. In genere la
+ caratteristica è disponibile nei sistemi che derivano da System V e non
+ disponibile per quelli che derivano da BSD.}
+
+Uno dei problemi che si presentano con l'uso di \func{select} è che il suo
+comportamento dipende dal valore del file descriptor che si vuole tenere sotto
+controllo. Infatti il kernel riceve con \param{n} un valore massimo per tale
+valore, e per capire quali sono i file descriptor da tenere sotto controllo
+dovrà effettuare una scansione su tutto l'intervallo, che può anche essere
+anche molto ampio anche se i file descriptor sono solo poche unità; tutto ciò
+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{n} 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_timeval_struct}) per
+indicare con maggiore precisione il timeout e non ne aggiorna il valore in
+caso di interruzione. 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 variabile globale e controllare questa
+nel corpo principale del programma; abbiamo visto in
+sez.~\ref{sec:sig_example} come questo lasci spazio a possibili 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 \textit{race
+ condition},\itindex{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ò non è
+ presente la relativa system call, e la funzione è implementata nelle
+ \acr{glibc} attraverso \func{select} (vedi \texttt{man select\_tut}) per cui
+ la possibilità di \itindex{race~condition}\textit{race condition} permane;
+ esiste però una soluzione, 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, e indicare l'arrivo di un segnale scrivendo sul capo in scrittura
+ all'interno del manipolatore; 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{La funzione \func{poll}}
+\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
+ \macro{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}).
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/pollfd.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{pollfd}, utilizzata per specificare le
+ modalità di controllo di un file descriptor alla funzione \func{poll}.}
+ \label{fig:file_pollfd}
+\end{figure}
+
+Per ciascun file da controllare deve essere inizializzata una struttura
+\struct{pollfd} nel vettore indicato dall'argomento \param{ufds}. La
+struttura, la cui definizione è riportata in fig.~\ref{fig:file_pollfd},
+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.
+
+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 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{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}
+
+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 \textit{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 (come \const{POLLRDNORM} e
+\const{POLLRDBAND}) 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}.
+
+
+%\subsection{L'interfaccia di \textit{epoll}}
+%\label{sec:file_epoll}
+% placeholder ...
+
+% TODO epoll
+
+\section{L'accesso \textsl{asincrono} ai file}
+\label{sec:file_asyncronous_access}
+
+Benché l'\textit{I/O multiplexing} sia stata la prima, e sia tutt'ora una fra
+le più diffuse modalità di gestire l'I/O in situazioni complesse in cui si
+debba operare su più file contemporaneamente, esistono altre modalità di
+gestione delle stesse problematiche. In particolare sono importanti in questo
+contesto le modalità di accesso ai file eseguibili in maniera
+\textsl{asincrona}, quelle cioè in cui un processo non deve bloccarsi in
+attesa della disponibilità dell'accesso al file, ma può proseguire
+nell'esecuzione utilizzando invece un meccanismo di notifica asincrono (di
+norma un segnale), per essere avvisato della possibilità di eseguire le
+operazioni di I/O volute.
+
+
+\subsection{Operazioni asincrone sui file}
+\label{sec:file_asyncronous_operation}
+
+Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso l'uso
+del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei
+ comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è specifico
+ di Linux e BSD.} aprire un file in modalità asincrona, così come è possibile
+attivare in un secondo tempo questa modalità impostando questo flag attraverso
+l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
+sez.~\ref{sec:file_fcntl}).
+
+In realtà in questo caso non si tratta di eseguire delle operazioni di lettura
+o scrittura del file in modo asincrono (tratteremo questo, che più
+propriamente è detto \textsl{I/O asincrono} in
+sez.~\ref{sec:file_asyncronous_io}), quanto di un meccanismo asincrono di
+notifica delle variazione dello stato del file descriptor aperto in questo
+modo.
+
+Quello che succede in questo caso è che il sistema genera un segnale
+(normalmente \const{SIGIO}, ma è possibile usarne altri con il comando
+\const{F\_SETSIG} di \func{fcntl}) tutte le volte che diventa possibile
+leggere o scrivere dal file descriptor che si è posto in questa modalità. Si
+può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
+quale processo (o gruppo di processi) riceverà il segnale. Se pertanto si
+effettuano le operazioni di I/O in risposta alla ricezione del segnale non ci
+sarà più la necessità di restare bloccati in attesa della disponibilità di
+accesso ai file; per questo motivo Stevens chiama questa modalità
+\textit{signal driven I/O}.
+
+In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select}
+che, quando vengono usate con un numero molto grande di file descriptor, non
+hanno buone prestazioni. % aggiungere cenno a epoll quando l'avrò scritta
+ In tal caso infatti la maggior parte del loro tempo
+di esecuzione è impegnato ad eseguire una scansione su tutti i file descriptor
+tenuti sotto controllo per determinare quali di essi (in genere una piccola
+percentuale) sono diventati attivi.
+
+Tuttavia con l'implementazione classica dei segnali questa modalità di I/O
+presenta notevoli problemi, dato che non è possibile determinare, quando i
+file descriptor sono più di uno, qual è quello responsabile dell'emissione del
+segnale. Inoltre dato che i segnali normali non si accodano (si ricordi quanto
+illustrato in sez.~\ref{sec:sig_notification}), in presenza di più file
+descriptor attivi contemporaneamente, più segnali emessi nello stesso momento
+verrebbero notificati una volta sola. Linux però supporta le estensioni
+POSIX.1b dei segnali real-time, che vengono accodati e che permettono di
+riconoscere il file descriptor che li ha emessi. In questo caso infatti si può
+fare ricorso alle informazioni aggiuntive restituite attraverso la struttura
+\struct{siginfo\_t}, utilizzando la forma estesa \var{sa\_sigaction} del
+gestore installata con il flag \const{SA\_SIGINFO} (si riveda quanto
+illustrato in sez.~\ref{sec:sig_sigaction}).
+
+Per far questo però occorre utilizzare le funzionalità dei segnali real-time
+(vedi sez.~\ref{sec:sig_real_time}) impostando esplicitamente con il comando
+\const{F\_SETSIG} di \func{fcntl} un segnale real-time da inviare in caso di
+I/O asincrono (il segnale predefinito è \const{SIGIO}). In questo caso il
+gestore, tutte le volte che riceverà \const{SI\_SIGIO} come valore del
+campo \var{si\_code}\footnote{il valore resta \const{SI\_SIGIO} qualunque sia
+ il segnale che si è associato all'I/O asincrono, ed indica appunto che il
+ segnale è stato generato a causa di attività nell'I/O asincrono.} di
+\struct{siginfo\_t}, troverà nel campo \var{si\_fd} il valore del file
+descriptor che ha generato il segnale.
+
+Un secondo vantaggio dell'uso dei segnali real-time è che essendo questi
+ultimi dotati di una coda di consegna ogni segnale sarà associato ad uno solo
+file descriptor; inoltre sarà possibile stabilire delle priorità nella
+risposta a seconda del segnale usato, dato che i segnali real-time supportano
+anche questa funzionalità. In questo modo si può identificare immediatamente
+un file su cui l'accesso è diventato possibile evitando completamente l'uso di
+funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
+la coda. Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non
+potendo più assicurare il comportamento corretto per un segnale real-time,
+invierà al suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti
+i segnali in eccesso, e si dovrà allora determinare con un ciclo quali sono i
+file diventati attivi.
+
+% TODO fare esempio che usa O_ASYNC
+
+
+\subsection{I meccanismi di notifica asincrona.}
+\label{sec:file_asyncronous_lease}
+
+Una delle domande più frequenti nella programmazione in ambiente unix-like è
+quella di come fare a sapere quando un file viene modificato. La
+risposta\footnote{o meglio la non risposta, tanto che questa nelle Unix FAQ
+ \cite{UnixFAQ} viene anche chiamata una \textit{Frequently Unanswered
+ Question}.} è che nell'architettura classica di Unix questo non è
+possibile. Al contrario di altri sistemi operativi infatti un kernel unix-like
+non prevede alcun meccanismo per cui un processo possa essere
+\textsl{notificato} di eventuali modifiche avvenute su un file. Questo è il
+motivo per cui i demoni devono essere \textsl{avvisati} in qualche
+modo\footnote{in genere questo vien fatto inviandogli un segnale di
+ \const{SIGHUP} che, per convenzione adottata dalla gran parte di detti
+ programmi, causa la rilettura della configurazione.} se il loro file di
+configurazione è stato modificato, perché possano rileggerlo e riconoscere le
+modifiche.
+
+Questa scelta è stata fatta perché provvedere un simile meccanismo a livello
+generale comporterebbe un notevole aumento di complessità dell'architettura
+della gestione dei file, per fornire una funzionalità necessaria soltanto in
+casi particolari. Dato che all'origine di Unix i soli programmi che potevano
+avere una tale esigenza erano i demoni, attenendosi a uno dei criteri base
+della progettazione, che era di far fare al kernel solo le operazioni
+strettamente necessarie e lasciare tutto il resto a processi in user space,
+non era stata prevista nessuna funzionalità di notifica.
+
+Visto però il crescente interesse nei confronti di una funzionalità di questo
+tipo (molto richiesta specialmente nello sviluppo dei programmi ad interfaccia
+grafica) sono state successivamente introdotte delle estensioni che
+permettessero la creazione di meccanismi di notifica più efficienti dell'unica
+soluzione disponibile con l'interfaccia tradizionale, che è quella del
+\itindex{polling}\textit{polling}.
+
+Queste nuove funzionalità sono delle estensioni specifiche, non
+standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel
+supportano meccanismi simili). Esse sono realizzate, e solo a partire dalla
+versione 2.4 del kernel, attraverso l'uso di alcuni \textsl{comandi}
+aggiuntivi per la funzione \func{fcntl} (vedi sez.~\ref{sec:file_fcntl}), che
+divengono disponibili soltanto se si è definita la macro \macro{\_GNU\_SOURCE}
+prima di includere \file{fcntl.h}.
+
+\index{file!lease|(}
+
+La prima di queste funzionalità è quella del cosiddetto \textit{file lease};
+questo è un meccanismo che consente ad un processo, detto \textit{lease
+ holder}, di essere notificato quando un altro processo, chiamato a sua volta
+\textit{lease breaker}, cerca di eseguire una \func{open} o una
+\func{truncate} sul file del quale l'\textit{holder} detiene il
+\textit{lease}.
+
+La notifica avviene in maniera analoga a come illustrato in precedenza per
+l'uso di \const{O\_ASYNC}: di default viene inviato al \textit{lease holder}
+il segnale \const{SIGIO}, ma questo segnale può essere modificato usando il
+comando \const{F\_SETSIG} di \func{fcntl}.\footnote{anche in questo caso si
+ può rispecificare lo stesso \const{SIGIO}.} Se si è fatto questo\footnote{è
+ in genere è opportuno farlo, come in precedenza, per utilizzare segnali
+ real-time.} e si è installato il manipolatore del segnale con
+\const{SA\_SIGINFO} si riceverà nel campo \var{si\_fd} della struttura
+\struct{siginfo\_t} il valore del file descriptor del file sul quale è stato
+compiuto l'accesso; in questo modo un processo può mantenere anche più di un
+\textit{file lease}.
+
+Esistono due tipi di \textit{file lease}: di lettura (\textit{read lease}) e
+di scrittura (\textit{write lease}). Nel primo caso la notifica avviene quando
+un altro processo esegue l'apertura del file in scrittura o usa
+\func{truncate} per troncarlo. Nel secondo caso la notifica avviene anche se
+il file viene aperto il lettura; in quest'ultimo caso però il \textit{lease}
+può essere ottenuto solo se nessun altro processo ha aperto lo stesso file.
+
+Come accennato in sez.~\ref{sec:file_fcntl} il comando di \func{fcntl} che
+consente di acquisire un \textit{file lease} è \const{F\_SETLEASE}, che viene
+utilizzato anche per rilasciarlo. In tal caso il file descriptor \param{fd}
+passato a \func{fcntl} servirà come riferimento per il file su cui si vuole
+operare, mentre per indicare il tipo di operazione (acquisizione o rilascio)
+occorrerà specificare come valore dell'argomento \param{arg} di \func{fcntl}
+uno dei tre valori di tab.~\ref{tab:file_lease_fctnl}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{F\_RDLCK} & Richiede un \textit{read lease}.\\
+ \const{F\_WRLCK} & Richiede un \textit{write lease}.\\
+ \const{F\_UNLCK} & Rilascia un \textit{file lease}.\\
+ \hline
+ \end{tabular}
+ \caption{Costanti per i tre possibili valori dell'argomento \param{arg} di
+ \func{fcntl} quando usata con i comandi \const{F\_SETLEASE} e
+ \const{F\_GETLEASE}.}
+ \label{tab:file_lease_fctnl}
+\end{table}
+
+Se invece si vuole conoscere lo stato di eventuali \textit{file lease}
+occorrerà chiamare \func{fcntl} sul relativo file descriptor \param{fd} con il
+comando \const{F\_GETLEASE}, e si otterrà indietro nell'argomento \param{arg}
+uno dei valori di tab.~\ref{tab:file_lease_fctnl}, che indicheranno la
+presenza del rispettivo tipo di \textit{lease}, o, nel caso di
+\const{F\_UNLCK}, l'assenza di qualunque \textit{file lease}.
+
+Si tenga presente che un processo può mantenere solo un tipo di \textit{lease}
+su un file, e che un \textit{lease} può essere ottenuto solo su file di dati
+(pipe e dispositivi sono quindi esclusi). Inoltre un processo non privilegiato
+può ottenere un \textit{lease} soltanto per un file appartenente ad un
+\acr{uid} corrispondente a quello del processo. Soltanto un processo con
+privilegi di amministratore (cioè con la \itindex{capabilities} capability
+\const{CAP\_LEASE}) può acquisire \textit{lease} su qualunque file.
+
+Se su un file è presente un \textit{lease} quando il \textit{lease breaker}
+esegue una \func{truncate} o una \func{open} che confligge con
+esso,\footnote{in realtà \func{truncate} confligge sempre, mentre \func{open},
+ se eseguita in sola lettura, non confligge se si tratta di un \textit{read
+ lease}.} la funzione si blocca\footnote{a meno di non avere aperto il file
+ con \const{O\_NONBLOCK}, nel qual caso \func{open} fallirebbe con un errore
+ di \errcode{EWOULDBLOCK}.} e viene eseguita la notifica al \textit{lease
+ holder}, così che questo possa completare le sue operazioni sul file e
+rilasciare il \textit{lease}. In sostanza con un \textit{read lease} si
+rilevano i tentativi di accedere al file per modificarne i dati da parte di un
+altro processo, mentre con un \textit{write lease} si rilevano anche i
+tentativi di accesso in lettura. Si noti comunque che le operazioni di
+notifica avvengono solo in fase di apertura del file e non sulle singole
+operazioni di lettura e scrittura.