+L'utilizzo dei \textit{file lease} consente al \textit{lease holder} di
+assicurare la consistenza di un file, a seconda dei due casi, prima che un
+altro processo inizi con le sue operazioni di scrittura o di lettura su di
+esso. In genere un \textit{lease holder} che riceve una notifica deve
+provvedere a completare le necessarie operazioni (ad esempio scaricare
+eventuali buffer), per poi rilasciare il \textit{lease} così che il
+\textit{lease breaker} possa eseguire le sue operazioni. Questo si fa con il
+comando \const{F\_SETLEASE}, o rimuovendo il \textit{lease} con
+\const{F\_UNLCK}, o, nel caso di \textit{write lease} che confligge con una
+operazione di lettura, declassando il \textit{lease} a lettura con
+\const{F\_RDLCK}.
+
+Se il \textit{lease holder} non provvede a rilasciare il \textit{lease} entro
+il numero di secondi specificato dal parametro di sistema mantenuto in
+\sysctlfile{fs/lease-break-time} sarà il kernel stesso a rimuoverlo o
+declassarlo automaticamente (questa è una misura di sicurezza per evitare che
+un processo blocchi indefinitamente l'accesso ad un file acquisendo un
+\textit{lease}). Una volta che un \textit{lease} è stato rilasciato o
+declassato (che questo sia fatto dal \textit{lease holder} o dal kernel è lo
+stesso) le chiamate a \func{open} o \func{truncate} eseguite dal \textit{lease
+ breaker} rimaste bloccate proseguono automaticamente.
+
+Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da
+parte di più processi, l'uso dei \textit{file lease} non consente comunque di
+risolvere il problema di rilevare automaticamente quando un file o una
+directory vengono modificati,\footnote{questa funzionalità venne aggiunta
+ principalmente ad uso di Samba per poter facilitare l'emulazione del
+ comportamento di Windows sui file, ma ad oggi viene considerata una
+ interfaccia mal progettata ed il suo uso è fortemente sconsigliato a favore
+ di \textit{inotify}.} che è quanto necessario ad esempio ai programma di
+gestione dei file dei vari desktop grafici.
+
+\itindbeg{dnotify}
+
+Per risolvere questo problema a partire dal kernel 2.4 è stata allora creata
+un'altra interfaccia,\footnote{si ricordi che anche questa è una interfaccia
+ specifica di Linux che deve essere evitata se si vogliono scrivere programmi
+ portabili, e che le funzionalità illustrate sono disponibili soltanto se è
+ stata definita la macro \macro{\_GNU\_SOURCE}.} chiamata \textit{dnotify},
+che consente di richiedere una notifica quando una directory, o uno qualunque
+dei file in essa contenuti, viene modificato. Come per i \textit{file lease}
+la notifica avviene di default attraverso il segnale \signal{SIGIO}, ma se ne
+può utilizzare un altro, e di nuovo, per le ragioni già esposte in precedenza,
+è opportuno che si utilizzino dei segnali \textit{real-time}. Inoltre, come
+in precedenza, si potrà ottenere nel gestore del segnale il file descriptor
+che è stato modificato tramite il contenuto della struttura
+\struct{siginfo\_t}.
+
+\itindend{file~lease}
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{DN\_ACCESS} & Un file è stato acceduto, con l'esecuzione di una fra
+ \func{read}, \func{pread}, \func{readv}.\\
+ \const{DN\_MODIFY} & Un file è stato modificato, con l'esecuzione di una
+ fra \func{write}, \func{pwrite}, \func{writev},
+ \func{truncate}, \func{ftruncate}.\\
+ \const{DN\_CREATE} & È stato creato un file nella directory, con
+ l'esecuzione di una fra \func{open}, \func{creat},
+ \func{mknod}, \func{mkdir}, \func{link},
+ \func{symlink}, \func{rename} (da un'altra
+ directory).\\
+ \const{DN\_DELETE} & È stato cancellato un file dalla directory con
+ l'esecuzione di una fra \func{unlink}, \func{rename}
+ (su un'altra directory), \func{rmdir}.\\
+ \const{DN\_RENAME} & È stato rinominato un file all'interno della
+ directory (con \func{rename}).\\
+ \const{DN\_ATTRIB} & È stato modificato un attributo di un file con
+ l'esecuzione di una fra \func{chown}, \func{chmod},
+ \func{utime}.\\
+ \const{DN\_MULTISHOT}& Richiede una notifica permanente di tutti gli
+ eventi.\\
+ \hline
+ \end{tabular}
+ \caption{Le costanti che identificano le varie classi di eventi per i quali
+ si richiede la notifica con il comando \const{F\_NOTIFY} di \func{fcntl}.}
+ \label{tab:file_notify}
+\end{table}
+
+Ci si può registrare per le notifiche dei cambiamenti al contenuto di una
+certa directory eseguendo la funzione \func{fcntl} su un file descriptor
+associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso
+l'argomento \param{arg} di \func{fcntl} serve ad indicare per quali classi
+eventi si vuole ricevere la notifica, e prende come valore una maschera
+binaria composta dall'OR aritmetico di una o più delle costanti riportate in
+tab.~\ref{tab:file_notify}.
+
+A meno di non impostare in maniera esplicita una notifica permanente usando il
+valore \const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una
+sola volta quando si verifica uno qualunque fra gli eventi per i quali la si è
+richiesta. Questo significa che un programma deve registrarsi un'altra volta
+se desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse
+chiamate con \const{F\_NOTIFY} e con valori diversi per \param{arg} questi
+ultimi si \textsl{accumulano}; cioè eventuali nuovi classi di eventi
+specificate in chiamate successive vengono aggiunte a quelle già impostate
+nelle precedenti. Se si vuole rimuovere la notifica si deve invece
+specificare un valore nullo.
+
+\itindbeg{inotify}
+
+Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve
+usare un file descriptor per ciascuna directory che si vuole tenere sotto
+controllo, il che porta facilmente ad avere un eccesso di file aperti. Inoltre
+quando la directory che si controlla è all'interno di un dispositivo
+rimovibile, mantenere il relativo file descriptor aperto comporta
+l'impossibilità di smontare il dispositivo e di rimuoverlo, il che in genere
+complica notevolmente la gestione dell'uso di questi dispositivi.
+
+Un altro problema è che l'interfaccia di \textit{dnotify} consente solo di
+tenere sotto controllo il contenuto di una directory; la modifica di un file
+viene segnalata, ma poi è necessario verificare di quale file si tratta
+(operazione che può essere molto onerosa quando una directory contiene un gran
+numero di file). Infine l'uso dei segnali come interfaccia di notifica
+comporta tutti i problemi di gestione visti in sez.~\ref{sec:sig_management} e
+sez.~\ref{sec:sig_adv_control}. Per tutta questa serie di motivi in generale
+quella di \textit{dnotify} viene considerata una interfaccia di usabilità
+problematica ed il suo uso oggi è fortemente sconsigliato.
+
+\itindend{dnotify}
+
+Per risolvere i problemi appena illustrati è stata introdotta una nuova
+interfaccia per l'osservazione delle modifiche a file o directory, chiamata
+\textit{inotify}.\footnote{l'interfaccia è disponibile a partire dal kernel
+ 2.6.13, le relative funzioni sono state introdotte nelle glibc 2.4.} Anche
+questa è una interfaccia specifica di Linux (pertanto non deve essere usata se
+si devono scrivere programmi portabili), ed è basata sull'uso di una coda di
+notifica degli eventi associata ad un singolo file descriptor, il che permette
+di risolvere il principale problema di \itindex{dnotify} \textit{dnotify}. La
+coda viene creata attraverso la funzione di sistema \funcd{inotify\_init}, il
+cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/inotify.h}
+\fdecl{int inotify\_init(void)}
+\fdesc{Inizializza una istanza di \textit{inotify}.}
+}
+
+{La funzione ritornaun 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{EMFILE}] si è raggiunto il numero massimo di istanze di
+ \textit{inotify} consentite all'utente.
+ \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
+ nel sistema.
+ \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
+ l'istanza.
+ \end{errlist}
+}
+\end{funcproto}
+
+La funzione non prende alcun argomento; inizializza una istanza di
+\textit{inotify} e restituisce un file descriptor attraverso il quale verranno
+effettuate le operazioni di notifica; si tratta di un file descriptor speciale
+che non è associato a nessun file su disco, e che viene utilizzato solo per
+notificare gli eventi che sono stati posti in osservazione. Per evitare abusi
+delle risorse di sistema è previsto che un utente possa utilizzare un numero
+limitato di istanze di \textit{inotify}; il valore di default del limite è di
+128, ma questo valore può essere cambiato con \func{sysctl} o usando il file
+\sysctlfile{fs/inotify/max\_user\_instances}.
+
+Dato che questo file descriptor non è associato a nessun file o directory
+reale, l'inconveniente di non poter smontare un filesystem i cui file sono
+tenuti sotto osservazione viene completamente eliminato; anzi, una delle
+capacità dell'interfaccia di \textit{inotify} è proprio quella di notificare
+il fatto che il filesystem su cui si trova il file o la directory osservata è
+stato smontato.
+
+Inoltre trattandosi di un file descriptor a tutti gli effetti, esso potrà
+essere utilizzato come argomento per le funzioni \func{select} e \func{poll} e
+con l'interfaccia di \textit{epoll}, ed a partire dal kernel 2.6.25 è stato
+introdotto anche il supporto per il \itindex{signal~driven~I/O}
+\texttt{signal-driven I/O}. Siccome gli eventi vengono notificati come dati
+disponibili in lettura, dette funzioni ritorneranno tutte le volte che si avrà
+un evento di notifica.
+
+Così, invece di dover utilizzare i segnali, considerati una pessima scelta dal
+punto di vista dell'interfaccia utente, si potrà gestire l'osservazione degli
+eventi con una qualunque delle modalità di \textit{I/O multiplexing}
+illustrate in sez.~\ref{sec:file_multiplexing}. Qualora si voglia cessare
+l'osservazione, sarà sufficiente chiudere il file descriptor e tutte le
+risorse allocate saranno automaticamente rilasciate. Infine l'interfaccia di
+\textit{inotify} consente di mettere sotto osservazione, oltre che una
+directory, anche singoli file.
+
+Una volta creata la coda di notifica si devono definire gli eventi da tenere
+sotto osservazione; questo viene fatto attraverso una \textsl{lista di
+ osservazione} (o \textit{watch list}) che è associata alla coda. Per gestire
+la lista di osservazione l'interfaccia fornisce due funzioni di sistema, la
+prima di queste è \funcd{inotify\_add\_watch}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/inotify.h}
+\fdecl{int inotify\_add\_watch(int fd, const char *pathname, uint32\_t mask)}
+\fdesc{Aggiunge un evento di osservazione a una lista di osservazione.}
+}
+
+{La funzione ritorna un valore positivo in caso di successo, o $-1$ per un
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EACCES}] non si ha accesso in lettura al file indicato.
+ \item[\errcode{EINVAL}] \param{mask} non contiene eventi legali o \param{fd}
+ non è un file descriptor di \textit{inotify}.
+ \item[\errcode{ENOSPC}] si è raggiunto il numero massimo di voci di
+ osservazione o il kernel non ha potuto allocare una risorsa necessaria.
+ \end{errlist}
+ ed inoltre \errval{EFAULT}, \errval{ENOMEM} e \errval{EBADF} nel loro
+ significato generico.}
+\end{funcproto}
+
+La funzione consente di creare un ``\textsl{osservatore}'' (il cosiddetto
+``\textit{watch}'') nella lista di osservazione di una coda di notifica, che
+deve essere indicata specificando il file descriptor ad essa associato
+nell'argomento \param{fd}, che ovviamente dovrà essere un file descriptor
+creato con \func{inotify\_init}. Il file o la directory da porre sotto
+osservazione vengono invece indicati per nome, da passare
+nell'argomento \param{pathname}. Infine il terzo argomento, \param{mask},
+indica che tipo di eventi devono essere tenuti sotto osservazione e le
+modalità della stessa. L'operazione può essere ripetuta per tutti i file e le
+directory che si vogliono tenere sotto osservazione,\footnote{anche in questo
+ caso c'è un limite massimo che di default è pari a 8192, ed anche questo
+ valore può essere cambiato con \func{sysctl} o usando il file
+ \sysctlfile{fs/inotify/max\_user\_watches}.} e si utilizzerà sempre un solo
+file descriptor.
+
+Il tipo di evento che si vuole osservare deve essere specificato
+nell'argomento \param{mask} come maschera binaria, combinando i valori delle
+costanti riportate in tab.~\ref{tab:inotify_event_watch} che identificano i
+singoli bit della maschera ed il relativo significato. In essa si sono marcati
+con un ``$\bullet$'' gli eventi che, quando specificati per una directory,
+vengono osservati anche su tutti i file che essa contiene. Nella seconda
+parte della tabella si sono poi indicate alcune combinazioni predefinite dei
+flag della prima parte.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|c|p{8cm}|}
+ \hline
+ \textbf{Valore} & & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{IN\_ACCESS} &$\bullet$& C'è stato accesso al file in
+ lettura.\\
+ \const{IN\_ATTRIB} &$\bullet$& Ci sono stati cambiamenti sui dati
+ dell'\itindex{inode} \textit{inode}
+ (o sugli attributi estesi, vedi
+ sez.~\ref{sec:file_xattr}).\\
+ \const{IN\_CLOSE\_WRITE} &$\bullet$& È stato chiuso un file aperto in
+ scrittura.\\
+ \const{IN\_CLOSE\_NOWRITE}&$\bullet$& È stato chiuso un file aperto in
+ sola lettura.\\
+ \const{IN\_CREATE} &$\bullet$& È stato creato un file o una
+ directory in una directory sotto
+ osservazione.\\
+ \const{IN\_DELETE} &$\bullet$& È stato cancellato un file o una
+ directory in una directory sotto
+ osservazione.\\
+ \const{IN\_DELETE\_SELF} & -- & È stato cancellato il file (o la
+ directory) sotto osservazione.\\
+ \const{IN\_MODIFY} &$\bullet$& È stato modificato il file.\\
+ \const{IN\_MOVE\_SELF} & & È stato rinominato il file (o la
+ directory) sotto osservazione.\\
+ \const{IN\_MOVED\_FROM} &$\bullet$& Un file è stato spostato fuori dalla
+ directory sotto osservazione.\\
+ \const{IN\_MOVED\_TO} &$\bullet$& Un file è stato spostato nella
+ directory sotto osservazione.\\
+ \const{IN\_OPEN} &$\bullet$& Un file è stato aperto.\\
+ \hline
+ \const{IN\_CLOSE} & & Combinazione di
+ \const{IN\_CLOSE\_WRITE} e
+ \const{IN\_CLOSE\_NOWRITE}.\\
+ \const{IN\_MOVE} & & Combinazione di
+ \const{IN\_MOVED\_FROM} e
+ \const{IN\_MOVED\_TO}.\\
+ \const{IN\_ALL\_EVENTS} & & Combinazione di tutti i flag
+ possibili.\\
+ \hline
+ \end{tabular}
+ \caption{Le costanti che identificano i bit della maschera binaria
+ dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano il
+ tipo di evento da tenere sotto osservazione.}
+ \label{tab:inotify_event_watch}
+\end{table}
+
+Oltre ai flag di tab.~\ref{tab:inotify_event_watch}, che indicano il tipo di
+evento da osservare e che vengono utilizzati anche in uscita per indicare il
+tipo di evento avvenuto, \func{inotify\_add\_watch} supporta ulteriori
+flag,\footnote{i flag \const{IN\_DONT\_FOLLOW}, \const{IN\_MASK\_ADD} e
+ \const{IN\_ONLYDIR} sono stati introdotti a partire dalle glibc 2.5, se si
+ usa la versione 2.4 è necessario definirli a mano.} riportati in
+tab.~\ref{tab:inotify_add_watch_flag}, che indicano le modalità di
+osservazione (da passare sempre nell'argomento \param{mask}) e che al
+contrario dei precedenti non vengono mai impostati nei risultati in uscita.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{IN\_DONT\_FOLLOW}& Non dereferenzia \param{pathname} se questo è un
+ link simbolico.\\
+ \const{IN\_MASK\_ADD} & Aggiunge a quelli già impostati i flag indicati
+ nell'argomento \param{mask}, invece di
+ sovrascriverli.\\
+ \const{IN\_ONESHOT} & Esegue l'osservazione su \param{pathname} per una
+ sola volta, rimuovendolo poi dalla \textit{watch
+ list}.\\
+ \const{IN\_ONLYDIR} & Se \param{pathname} è una directory riporta
+ soltanto gli eventi ad essa relativi e non
+ quelli per i file che contiene.\\
+ \hline
+ \end{tabular}
+ \caption{Le costanti che identificano i bit della maschera binaria
+ dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano le
+ modalità di osservazione.}
+ \label{tab:inotify_add_watch_flag}
+\end{table}
+
+Se non esiste nessun \textit{watch} per il file o la directory specificata
+questo verrà creato per gli eventi specificati dall'argomento \param{mask},
+altrimenti la funzione sovrascriverà le impostazioni precedenti, a meno che
+non si sia usato il flag \const{IN\_MASK\_ADD}, nel qual caso gli eventi
+specificati saranno aggiunti a quelli già presenti.
+
+Come accennato quando si tiene sotto osservazione una directory vengono
+restituite le informazioni sia riguardo alla directory stessa che ai file che
+essa contiene; questo comportamento può essere disabilitato utilizzando il
+flag \const{IN\_ONLYDIR}, che richiede di riportare soltanto gli eventi
+relativi alla directory stessa. Si tenga presente inoltre che quando si
+osserva una directory vengono riportati solo gli eventi sui file che essa
+contiene direttamente, non quelli relativi a file contenuti in eventuali
+sottodirectory; se si vogliono osservare anche questi sarà necessario creare
+ulteriori \textit{watch} per ciascuna sottodirectory.
+
+Infine usando il flag \const{IN\_ONESHOT} è possibile richiedere una notifica
+singola;\footnote{questa funzionalità però è disponibile soltanto a partire dal
+ kernel 2.6.16.} una volta verificatosi uno qualunque fra gli eventi
+richiesti con \func{inotify\_add\_watch} l'\textsl{osservatore} verrà
+automaticamente rimosso dalla lista di osservazione e nessun ulteriore evento
+sarà più notificato.
+
+In caso di successo \func{inotify\_add\_watch} ritorna un intero positivo,
+detto \textit{watch descriptor}, che identifica univocamente un
+\textsl{osservatore} su una coda di notifica; esso viene usato per farvi
+riferimento sia riguardo i risultati restituiti da \textit{inotify}, che per
+la eventuale rimozione dello stesso.
+
+La seconda funzione di sistema per la gestione delle code di notifica, che
+permette di rimuovere un \textsl{osservatore}, è \funcd{inotify\_rm\_watch},
+ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/inotify.h}
+\fdecl{int inotify\_rm\_watch(int fd, uint32\_t wd)}
+\fdesc{Rimuove un \textsl{osservatore} da una coda di notifica.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] non si è specificato in \param{fd} un file descriptor
+ valido.
+ \item[\errcode{EINVAL}] il valore di \param{wd} non è corretto, o \param{fd}
+ non è associato ad una coda di notifica.
+ \end{errlist}
+}
+\end{funcproto}
+
+La funzione rimuove dalla coda di notifica identificata dall'argomento
+\param{fd} l'osservatore identificato dal \textit{watch descriptor}
+\param{wd}; ovviamente deve essere usato per questo argomento un valore
+ritornato da \func{inotify\_add\_watch}, altrimenti si avrà un errore di
+\errval{EINVAL}. In caso di successo della rimozione, contemporaneamente alla
+cancellazione dell'osservatore, sulla coda di notifica verrà generato un
+evento di tipo \const{IN\_IGNORED} (vedi
+tab.~\ref{tab:inotify_read_event_flag}). Si tenga presente che se un file
+viene cancellato o un filesystem viene smontato i relativi osservatori vengono
+rimossi automaticamente e non è necessario utilizzare
+\func{inotify\_rm\_watch}.
+
+Come accennato l'interfaccia di \textit{inotify} prevede che gli eventi siano
+notificati come dati presenti in lettura sul file descriptor associato alla
+coda di notifica. Una applicazione pertanto dovrà leggere i dati da detto file
+con una \func{read}, che ritornerà sul buffer i dati presenti nella forma di
+una o più strutture di tipo \struct{inotify\_event} (la cui definizione è
+riportata in fig.~\ref{fig:inotify_event}). Qualora non siano presenti dati la
+\func{read} si bloccherà (a meno di non aver impostato il file descriptor in
+modalità non bloccante) fino all'arrivo di almeno un evento.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{0.90\textwidth}
+ \includestruct{listati/inotify_event.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{inotify\_event} usata dall'interfaccia di
+ \textit{inotify} per riportare gli eventi.}
+ \label{fig:inotify_event}
+\end{figure}
+
+Una ulteriore caratteristica dell'interfaccia di \textit{inotify} è che essa
+permette di ottenere con \func{ioctl}, come per i file descriptor associati ai
+socket (si veda sez.~\ref{sec:sock_ioctl_IP}), il numero di byte disponibili
+in lettura sul file descriptor, utilizzando su di esso l'operazione
+\const{FIONREAD}.\footnote{questa è una delle operazioni speciali per i file
+ (vedi sez.~\ref{sec:file_fcntl_ioctl}), che è disponibile solo per i socket
+ e per i file descriptor creati con \func{inotify\_init}.} Si può così
+utilizzare questa operazione, oltre che per predisporre una operazione di
+lettura con un buffer di dimensioni adeguate, anche per ottenere rapidamente
+il numero di file che sono cambiati.
+
+Una volta effettuata la lettura con \func{read} a ciascun evento sarà
+associata una struttura \struct{inotify\_event} contenente i rispettivi dati.
+Per identificare a quale file o directory l'evento corrisponde viene
+restituito nel campo \var{wd} il \textit{watch descriptor} con cui il relativo
+osservatore è stato registrato. Il campo \var{mask} contiene invece una
+maschera di bit che identifica il tipo di evento verificatosi; in essa
+compariranno sia i bit elencati nella prima parte di
+tab.~\ref{tab:inotify_event_watch}, che gli eventuali valori aggiuntivi di
+tab.~\ref{tab:inotify_read_event_flag} (questi compaiono solo nel campo
+\var{mask} di \struct{inotify\_event}, e non sono utilizzabili in fase di
+registrazione dell'osservatore).
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{10cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{IN\_IGNORED} & L'osservatore è stato rimosso, sia in maniera
+ esplicita con l'uso di \func{inotify\_rm\_watch},
+ che in maniera implicita per la rimozione
+ dell'oggetto osservato o per lo smontaggio del
+ filesystem su cui questo si trova.\\
+ \const{IN\_ISDIR} & L'evento avvenuto fa riferimento ad una directory
+ (consente così di distinguere, quando si pone
+ sotto osservazione una directory, fra gli eventi
+ relativi ad essa e quelli relativi ai file che
+ essa contiene).\\
+ \const{IN\_Q\_OVERFLOW}& Si sono eccedute le dimensioni della coda degli
+ eventi (\textit{overflow} della coda); in questo
+ caso il valore di \var{wd} è $-1$.\footnotemark\\
+ \const{IN\_UNMOUNT} & Il filesystem contenente l'oggetto posto sotto
+ osservazione è stato smontato.\\
+ \hline
+ \end{tabular}
+ \caption{Le costanti che identificano i bit aggiuntivi usati nella maschera
+ binaria del campo \var{mask} di \struct{inotify\_event}.}
+ \label{tab:inotify_read_event_flag}
+\end{table}
+
+\footnotetext{la coda di notifica ha una dimensione massima che viene
+ controllata dal parametro di sistema
+ \sysctlfile{fs/inotify/max\_queued\_events}, che indica il numero massimo di
+ eventi che possono essere mantenuti sulla stessa; quando detto valore viene
+ ecceduto gli ulteriori eventi vengono scartati, ma viene comunque generato
+ un evento di tipo \const{IN\_Q\_OVERFLOW}.}
+
+Il campo \var{cookie} contiene invece un intero univoco che permette di
+identificare eventi correlati (per i quali avrà lo stesso valore), al momento
+viene utilizzato soltanto per rilevare lo spostamento di un file, consentendo
+così all'applicazione di collegare la corrispondente coppia di eventi
+\const{IN\_MOVED\_TO} e \const{IN\_MOVED\_FROM}.
+
+Infine due campi \var{name} e \var{len} sono utilizzati soltanto quando
+l'evento è relativo ad un file presente in una directory posta sotto
+osservazione, in tal caso essi contengono rispettivamente il nome del file
+(come \itindsub{pathname}{relativo} \textit{pathname} relativo alla directory
+osservata) e la relativa dimensione in byte. Il campo \var{name} viene sempre
+restituito come stringa terminata da NUL, con uno o più zeri di terminazione,
+a seconda di eventuali necessità di allineamento del risultato, ed il valore
+di \var{len} corrisponde al totale della dimensione di \var{name}, zeri
+aggiuntivi compresi. La stringa con il nome del file viene restituita nella
+lettura subito dopo la struttura \struct{inotify\_event}; questo significa che
+le dimensioni di ciascun evento di \textit{inotify} saranno pari a
+\code{sizeof(\struct{inotify\_event}) + len}.
+
+Vediamo allora un esempio dell'uso dell'interfaccia di \textit{inotify} con un
+semplice programma che permette di mettere sotto osservazione uno o più file e
+directory. Il programma si chiama \texttt{inotify\_monitor.c} ed il codice
+completo è disponibile coi sorgenti allegati alla guida, il corpo principale
+del programma, che non contiene la sezione di gestione delle opzioni e le
+funzioni di ausilio è riportato in fig.~\ref{fig:inotify_monitor_example}.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/inotify_monitor.c}
+ \end{minipage}
+ \normalsize
+ \caption{Esempio di codice che usa l'interfaccia di \textit{inotify}.}
+ \label{fig:inotify_monitor_example}
+\end{figure}
+
+Una volta completata la scansione delle opzioni il corpo del programma inizia
+controllando (\texttt{\small 11-15}) che sia rimasto almeno un argomento che
+indichi quale file o directory mettere sotto osservazione (e qualora questo
+non avvenga esce stampando la pagina di aiuto); dopo di che passa
+(\texttt{\small 16-20}) all'inizializzazione di \textit{inotify} ottenendo con
+\func{inotify\_init} il relativo file descriptor (o si esce in caso di
+errore).
+
+Il passo successivo è aggiungere (\texttt{\small 21-30}) alla coda di
+notifica gli opportuni osservatori per ciascuno dei file o directory indicati
+all'invocazione del comando; questo viene fatto eseguendo un ciclo
+(\texttt{\small 22-29}) fintanto che la variabile \var{i}, inizializzata a
+zero (\texttt{\small 21}) all'inizio del ciclo, è minore del numero totale di
+argomenti rimasti. All'interno del ciclo si invoca (\texttt{\small 23})
+\func{inotify\_add\_watch} per ciascuno degli argomenti, usando la maschera
+degli eventi data dalla variabile \var{mask} (il cui valore viene impostato
+nella scansione delle opzioni), in caso di errore si esce dal programma
+altrimenti si incrementa l'indice (\texttt{\small 29}).
+
+Completa l'inizializzazione di \textit{inotify} inizia il ciclo principale
+(\texttt{\small 32-56}) del programma, nel quale si resta in attesa degli
+eventi che si intendono osservare. Questo viene fatto eseguendo all'inizio del
+ciclo (\texttt{\small 33}) una \func{read} che si bloccherà fintanto che non
+si saranno verificati eventi.
+
+Dato che l'interfaccia di \textit{inotify} può riportare anche più eventi in
+una sola lettura, si è avuto cura di passare alla \func{read} un buffer di
+dimensioni adeguate, inizializzato in (\texttt{\small 7}) ad un valore di
+approssimativamente 512 eventi (si ricordi che la quantità di dati restituita
+da \textit{inotify} è variabile a causa della diversa lunghezza del nome del
+file restituito insieme a \struct{inotify\_event}). In caso di errore di
+lettura (\texttt{\small 35-40}) il programma esce con un messaggio di errore
+(\texttt{\small 37-39}), a meno che non si tratti di una interruzione della
+\textit{system call}, nel qual caso (\texttt{\small 36}) si ripete la lettura.
+
+Se la lettura è andata a buon fine invece si esegue un ciclo (\texttt{\small
+ 43-52}) per leggere tutti gli eventi restituiti, al solito si inizializza
+l'indice \var{i} a zero (\texttt{\small 42}) e si ripetono le operazioni
+(\texttt{\small 43}) fintanto che esso non supera il numero di byte restituiti
+in lettura. Per ciascun evento all'interno del ciclo si assegna alla variabile
+\var{event} (si noti come si sia eseguito un opportuno \textit{casting} del
+puntatore) l'indirizzo nel buffer della corrispondente struttura
+\struct{inotify\_event} (\texttt{\small 44}), e poi si stampano il numero di
+\textit{watch descriptor} (\texttt{\small 45}) ed il file a cui questo fa
+riferimento (\texttt{\small 46}), ricavato dagli argomenti passati a riga di
+comando sfruttando il fatto che i \textit{watch descriptor} vengono assegnati
+in ordine progressivo crescente a partire da 1.
+
+Qualora sia presente il riferimento ad un nome di file associato all'evento lo
+si stampa (\texttt{\small 47-49}); si noti come in questo caso si sia
+controllato il valore del campo \var{event->len} e non il fatto che
+\var{event->name} riporti o meno un puntatore nullo. L'interfaccia infatti,
+qualora il nome non sia presente, non tocca il campo \var{event->name}, che
+si troverà pertanto a contenere quello che era precedentemente presente nella
+rispettiva locazione di memoria, nel caso più comune il puntatore al nome di
+un file osservato in precedenza.
+
+Si utilizza poi (\texttt{\small 50}) la funzione \code{printevent}, che
+interpreta il valore del campo \var{event->mask}, per stampare il tipo di
+eventi accaduti.\footnote{per il relativo codice, che non riportiamo in quanto
+ non essenziale alla comprensione dell'esempio, si possono utilizzare
+ direttamente i sorgenti allegati alla guida.} Infine (\texttt{\small 51}) si
+provvede ad aggiornare l'indice \var{i} per farlo puntare all'evento
+successivo.
+
+Se adesso usiamo il programma per mettere sotto osservazione una directory, e
+da un altro terminale eseguiamo il comando \texttt{ls} otterremo qualcosa del
+tipo di:
+\begin{Console}
+piccardi@gethen:~/gapil/sources$ \textbf{./inotify_monitor -a /home/piccardi/gapil/}
+Watch descriptor 1
+Observed event on /home/piccardi/gapil/
+IN_OPEN,
+Watch descriptor 1
+Observed event on /home/piccardi/gapil/
+IN_CLOSE_NOWRITE,
+\end{Console}
+%$
+
+I lettori più accorti si saranno resi conto che nel ciclo di lettura degli
+eventi appena illustrato non viene trattato il caso particolare in cui la
+funzione \func{read} restituisce in \var{nread} un valore nullo. Lo si è fatto
+perché con \textit{inotify} il ritorno di una \func{read} con un valore nullo
+avviene soltanto, come forma di avviso, quando si sia eseguita la funzione
+specificando un buffer di dimensione insufficiente a contenere anche un solo
+evento. Nel nostro caso le dimensioni erano senz'altro sufficienti, per cui
+tale evenienza non si verificherà mai.
+
+Ci si potrà però chiedere cosa succede se il buffer è sufficiente per un
+evento, ma non per tutti gli eventi verificatisi. Come si potrà notare nel
+codice illustrato in precedenza non si è presa nessuna precauzione per
+verificare che non ci fossero stati troncamenti dei dati. Anche in questo caso
+il comportamento scelto è corretto, perché l'interfaccia di \textit{inotify}
+garantisce automaticamente, anche quando ne sono presenti in numero maggiore,
+di restituire soltanto il numero di eventi che possono rientrare completamente
+nelle dimensioni del buffer specificato.\footnote{si avrà cioè, facendo
+ riferimento sempre al codice di fig.~\ref{fig:inotify_monitor_example}, che
+ \var{read} sarà in genere minore delle dimensioni di \var{buffer} ed uguale
+ soltanto qualora gli eventi corrispondano esattamente alle dimensioni di
+ quest'ultimo.} Se gli eventi sono di più saranno restituiti solo quelli che
+entrano interamente nel buffer e gli altri saranno restituiti alla successiva
+chiamata di \func{read}.
+
+Infine un'ultima caratteristica dell'interfaccia di \textit{inotify} è che gli
+eventi restituiti nella lettura formano una sequenza ordinata, è cioè
+garantito che se si esegue uno spostamento di un file gli eventi vengano
+generati nella sequenza corretta. L'interfaccia garantisce anche che se si
+verificano più eventi consecutivi identici (vale a dire con gli stessi valori
+dei campi \var{wd}, \var{mask}, \var{cookie}, e \var{name}) questi vengono
+raggruppati in un solo evento.
+
+\itindend{inotify}
+
+% TODO trattare fanotify, vedi http://lwn.net/Articles/339399/ e
+% http://lwn.net/Articles/343346/ (incluso nel 2.6.36)
+
+
+\subsection{L'interfaccia POSIX per l'I/O asincrono}
+\label{sec:file_asyncronous_io}
+
+Una modalità alternativa all'uso dell'\textit{I/O multiplexing} per gestione
+dell'I/O simultaneo su molti file è costituita dal cosiddetto \textsl{I/O
+ asincrono} o ``AIO''. Il concetto base dell'\textsl{I/O asincrono} è che le
+funzioni di I/O non attendono il completamento delle operazioni prima di
+ritornare, così che il processo non viene bloccato. In questo modo diventa ad
+esempio possibile effettuare una richiesta preventiva di dati, in modo da
+poter effettuare in contemporanea le operazioni di calcolo e quelle di I/O.
+
+Benché la modalità di apertura asincrona di un file vista in
+sez.~\ref{sec:signal_driven_io} possa risultare utile in varie occasioni (in
+particolar modo con i socket e gli altri file per i quali le funzioni di I/O
+sono \index{system~call~lente} \textit{system call} lente), essa è comunque
+limitata alla notifica della disponibilità del file descriptor per le
+operazioni di I/O, e non ad uno svolgimento asincrono delle medesime. Lo
+standard POSIX.1b definisce una interfaccia apposita per l'I/O asincrono vero
+e proprio,\footnote{questa è stata ulteriormente perfezionata nelle successive
+ versioni POSIX.1-2001 e POSIX.1-2008.} che prevede un insieme di funzioni
+dedicate per la lettura e la scrittura dei file, completamente separate
+rispetto a quelle usate normalmente.
+
+In generale questa interfaccia è completamente astratta e può essere
+implementata sia direttamente nel kernel che in user space attraverso l'uso di
+\itindex{thread} \textit{thread}. Per le versioni del kernel meno recenti
+esiste una implementazione di questa interfaccia fornita completamente delle
+\acr{glibc} a partire dalla versione 2.1, che è realizzata completamente in
+user space, ed è accessibile linkando i programmi con la libreria
+\file{librt}. A partire dalla versione 2.5.32 è stato introdotto nel kernel
+una nuova infrastruttura per l'I/O asincrono, ma ancora il supporto è parziale
+ed insufficiente ad implementare tutto l'AIO POSIX.
+
+Lo standard POSIX prevede che tutte le operazioni di I/O asincrono siano
+controllate attraverso l'uso di una apposita struttura \struct{aiocb} (il cui
+nome sta per \textit{asyncronous I/O control block}), che viene passata come
+argomento a tutte le funzioni dell'interfaccia. La sua definizione, come
+effettuata in \headfile{aio.h}, è riportata in
+fig.~\ref{fig:file_aiocb}. Nello steso file è definita la macro
+\macro{\_POSIX\_ASYNCHRONOUS\_IO}, che dichiara la disponibilità
+dell'interfaccia per l'I/O asincrono.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{0.90\textwidth}
+ \includestruct{listati/aiocb.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{aiocb}, usata per il controllo dell'I/O
+ asincrono.}
+ \label{fig:file_aiocb}
+\end{figure}
+
+Le operazioni di I/O asincrono possono essere effettuate solo su un file già
+aperto; il file deve inoltre supportare la funzione \func{lseek}, pertanto
+terminali e \textit{pipe} sono esclusi. Non c'è limite al numero di operazioni
+contemporanee effettuabili su un singolo file. Ogni operazione deve
+inizializzare opportunamente un \textit{control block}. Il file descriptor su
+cui operare deve essere specificato tramite il campo \var{aio\_fildes}; dato
+che più operazioni possono essere eseguita in maniera asincrona, il concetto
+di posizione corrente sul file viene a mancare; pertanto si deve sempre
+specificare nel campo \var{aio\_offset} la posizione sul file da cui i dati
+saranno letti o scritti. Nel campo \var{aio\_buf} deve essere specificato
+l'indirizzo del buffer usato per l'I/O, ed in \var{aio\_nbytes} la lunghezza
+del blocco di dati da trasferire.
+
+Il campo \var{aio\_reqprio} permette di impostare la priorità delle operazioni
+di I/O, in generale perché ciò sia possibile occorre che la piattaforma
+supporti questa caratteristica, questo viene indicato dal fatto che le macro
+\macro{\_POSIX\_PRIORITIZED\_IO}, e \macro{\_POSIX\_PRIORITY\_SCHEDULING} sono
+definite. La priorità viene impostata a partire da quella del processo
+chiamante (vedi sez.~\ref{sec:proc_priority}), cui viene sottratto il valore
+di questo campo. Il campo \var{aio\_lio\_opcode} è usato solo dalla funzione
+\func{lio\_listio}, che, come vedremo, permette di eseguire con una sola
+chiamata una serie di operazioni, usando un vettore di \textit{control
+ block}. Tramite questo campo si specifica quale è la natura di ciascuna di
+esse.
+
+Infine il campo \var{aio\_sigevent} è una struttura di tipo \struct{sigevent}
+(illustrata in in fig.~\ref{fig:struct_sigevent}) che serve a specificare il
+modo in cui si vuole che venga effettuata la notifica del completamento delle
+operazioni richieste; per la trattazione delle modalità di utilizzo della
+stessa si veda quanto già visto in proposito in sez.~\ref{sec:sig_timer_adv}.
+
+Le due funzioni base dell'interfaccia per l'I/O asincrono sono
+\funcd{aio\_read} ed \funcd{aio\_write}. Esse permettono di richiedere una
+lettura od una scrittura asincrona di dati usando la struttura \struct{aiocb}
+appena descritta; i rispettivi prototipi sono:
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_read(struct aiocb *aiocbp)}
+\fdesc{Richiede una lettura asincrona.}
+\fdecl{int aio\_write(struct aiocb *aiocbp)}
+\fdesc{Richiede una scrittura asincrona.}
+}
+
+{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EAGAIN}] la coda delle richieste è momentaneamente piena.
+ \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato.
+ \item[\errcode{EINVAL}] si è specificato un valore non valido per i campi
+ \var{aio\_offset} o \var{aio\_reqprio} di \param{aiocbp}.
+ \item[\errcode{ENOSYS}] la funzione non è implementata.
+ \end{errlist}
+}
+\end{funcproto}
+
+
+Entrambe le funzioni ritornano immediatamente dopo aver messo in coda la
+richiesta, o in caso di errore. Non è detto che gli errori \errcode{EBADF} ed
+\errcode{EINVAL} siano rilevati immediatamente al momento della chiamata,
+potrebbero anche emergere nelle fasi successive delle operazioni. Lettura e
+scrittura avvengono alla posizione indicata da \var{aio\_offset}, a meno che
+il file non sia stato aperto in \textit{append mode} (vedi
+sez.~\ref{sec:file_open_close}), nel qual caso le scritture vengono effettuate
+comunque alla fine del file, nell'ordine delle chiamate a \func{aio\_write}.
+
+Si tenga inoltre presente che deallocare la memoria indirizzata da
+\param{aiocbp} o modificarne i valori prima della conclusione di una
+operazione può dar luogo a risultati impredicibili, perché l'accesso ai vari
+campi per eseguire l'operazione può avvenire in un momento qualsiasi dopo la
+richiesta. Questo comporta che non si devono usare per \param{aiocbp}
+\index{variabili!automatiche} variabili automatiche e che non si deve
+riutilizzare la stessa struttura per un'altra operazione fintanto che la
+precedente non sia stata ultimata. In generale per ogni operazione si deve
+utilizzare una diversa struttura \struct{aiocb}.
+
+Dato che si opera in modalità asincrona, il successo di \func{aio\_read} o
+\func{aio\_write} non implica che le operazioni siano state effettivamente
+eseguite in maniera corretta; per verificarne l'esito l'interfaccia prevede
+altre due funzioni, che permettono di controllare lo stato di esecuzione. La
+prima è \funcd{aio\_error}, che serve a determinare un eventuale stato di
+errore; il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_error(const struct aiocb *aiocbp)}
+\fdesc{Determina lo stato di errore di una operazione di I/O asincrono.}
+}
+
+{La funzione ritorna $0$ se le operazioni si sono concluse con successo,
+ altrimenti restituisce \errval{EINPROGRESS} se non sono concluse,
+ \errcode{ECANCELED} se sono state cancellate o il relativo codice di errore
+ se sono fallite.}
+\end{funcproto}
+
+Se l'operazione non si è ancora completata viene sempre restituito l'errore di
+\errcode{EINPROGRESS}, mentre se è stata cancellata ritorna
+\errcode{ECANCELED}. La funzione ritorna zero quando l'operazione si è
+conclusa con successo, altrimenti restituisce il codice dell'errore
+verificatosi, ed esegue la corrispondente impostazione di \var{errno}. Il
+codice può essere sia \errcode{EINVAL} ed \errcode{EBADF}, dovuti ad un valore
+errato per \param{aiocbp}, che uno degli errori possibili durante l'esecuzione
+dell'operazione di I/O richiesta, nel qual caso saranno restituiti, a seconda
+del caso, i codici di errore delle \textit{system call} \func{read},
+\func{write}, \func{fsync} e \func{fdatasync}.
+
+Una volta che si sia certi che le operazioni siano state concluse (cioè dopo
+che una chiamata ad \func{aio\_error} non ha restituito
+\errcode{EINPROGRESS}), si potrà usare la funzione \funcd{aio\_return}, che
+permette di verificare il completamento delle operazioni di I/O asincrono; il
+suo prototipo è:
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{ssize\_t aio\_return(const struct aiocb *aiocbp)}
+\fdesc{Ottiene lo stato dei risultati di una operazione di I/O asincrono.}
+}
+
+{La funzione ritorna lo stato di uscita dell'operazione eseguita (il valore
+ che avrebbero restituito le equivalenti funzioni eseguite in maniera
+ sincrona).}
+\end{funcproto}
+
+La funzione recupera il valore dello stato di ritorno delle operazioni di I/O
+associate a \param{aiocbp} e deve essere chiamata una sola volta per ciascuna
+operazione asincrona, essa infatti fa sì che il sistema rilasci le risorse ad
+essa associate. É per questo motivo che occorre chiamare la funzione solo dopo
+che l'operazione cui \param{aiocbp} fa riferimento si è completata
+verificandolo con \func{aio\_error}, ed usarla una sola volta. Una chiamata
+precedente il completamento delle operazioni darebbe risultati indeterminati,
+così come chiamarla più di una volta.
+
+La funzione restituisce il valore di ritorno relativo all'operazione eseguita,
+così come ricavato dalla sottostante \textit{system call} (il numero di byte
+letti, scritti o il valore di ritorno di \func{fsync} o \func{fdatasync}). É
+importante chiamare sempre questa funzione, altrimenti le risorse disponibili
+per le operazioni di I/O asincrono non verrebbero liberate, rischiando di
+arrivare ad un loro esaurimento.
+
+Oltre alle operazioni di lettura e scrittura l'interfaccia POSIX.1b mette a
+disposizione un'altra operazione, quella di sincronizzazione dell'I/O,
+compiuta dalla funzione \funcd{aio\_fsync}, che ha lo stesso effetto della
+analoga \func{fsync}, ma viene eseguita in maniera asincrona; il suo prototipo
+è:
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_fsync(int op, struct aiocb *aiocbp)}
+\fdesc{Richiede la sincronizzazione dei dati su disco.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+ caso \var{errno} assumerà gli stessi valori visti \func{aio\_read} con lo
+ stesso significato.
+}
+\end{funcproto}
+
+La funzione richiede la sincronizzazione dei dati delle operazioni di I/O
+relative al file descriptor indicato in \texttt{aiocbp->aio\_fildes},
+ritornando immediatamente. Si tenga presente che la funzione mette
+semplicemente in coda la richiesta, l'esecuzione effettiva della
+sincronizzazione dovrà essere verificata con \func{aio\_error} e
+\func{aio\_return} come per le operazioni di lettura e
+scrittura. L'argomento \param{op} permette di indicare la modalità di
+esecuzione, se si specifica il valore \const{O\_DSYNC} le operazioni saranno
+completate con una chiamata a \func{fdatasync}, se si specifica
+\const{O\_SYNC} con una chiamata a \func{fsync} (per i dettagli vedi
+sez.~\ref{sec:file_sync}).
+
+Il successo della chiamata assicura la richiesta di sincronizzazione dei dati
+relativi operazioni di I/O asincrono richieste fino a quel momento, niente è
+garantito riguardo la sincronizzazione dei dati relativi ad eventuali
+operazioni richieste successivamente. Se si è specificato un meccanismo di
+notifica questo sarà innescato una volta che le operazioni di sincronizzazione
+dei dati saranno completate (\texttt{aio\_sigevent} è l'unico altro campo
+di \param{aiocbp} che viene usato.
+
+In alcuni casi può essere necessario interrompere le operazioni di I/O (in
+genere quando viene richiesta un'uscita immediata dal programma), per questo
+lo standard POSIX.1b prevede una funzione apposita, \funcd{aio\_cancel}, che
+permette di cancellare una operazione richiesta in precedenza; il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{aio.h}
+\fdecl{int aio\_cancel(int fd, struct aiocb *aiocbp)}
+\fdesc{Richiede la cancellazione delle operazioni di I/O asincrono.}
+}
+
+{La funzione ritorna un intero positivo che indica il risultato
+ dell'operazione in caso di successo e $-1$ per un errore, nel qual caso
+ \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\errcode{EBADF}] \param{fd} non è un file descriptor valido.
+ \item[\errcode{ENOSYS}] la funzione non è implementata.
+ \end{errlist}
+}
+\end{funcproto}
+
+La funzione permette di cancellare una operazione specifica sul file
+\param{fd}, idicata con \param{aiocbp}, o tutte le operazioni pendenti,
+specificando \val{NULL} come valore di \param{aiocbp}. Quando una operazione
+viene cancellata una successiva chiamata ad \func{aio\_error} riporterà
+\errcode{ECANCELED} come codice di errore, ed mentre il valore di ritorno per
+\func{aio\_return} sarà $-1$, inoltre il meccanismo di notifica non verrà
+invocato. Se con \param{aiocbp} si specifica una operazione relativa ad un
+file descriptor diverso da \param{fd} il risultato è indeterminato. In caso
+di successo, i possibili valori di ritorno per \func{aio\_cancel} (anch'essi
+definiti in \headfile{aio.h}) sono tre:
+\begin{basedescript}{\desclabelwidth{3.0cm}}
+\item[\const{AIO\_ALLDONE}] indica che le operazioni di cui si è richiesta la
+ cancellazione sono state già completate,