Modifiche con il kernel 4.17
[gapil.git] / fileadv.tex
index 600808fa322d34650b99b2023c498075c9767564..3b560d7b57802ca53131e2c3515f2716eed08729 100644 (file)
-capacità \const{CAP\_LEASE}, vedi sez.~\ref{sec:proc_capabilities}) può
-acquisire \textit{lease} su qualunque file.
+%% fileadv.tex
+%%
+%% Copyright (C) 2000-2018 Simone Piccardi.  Permission is granted to
+%% copy, distribute and/or modify this document under the terms of the GNU Free
+%% Documentation License, Version 1.1 or any later version published by the
+%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
+%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
+%% license is included in the section entitled "GNU Free Documentation
+%% License".
+%%
+\chapter{La gestione avanzata dei file}
+\label{cha:file_advanced}
+
+In questo capitolo affronteremo le tematiche relative alla gestione avanzata
+dei file. Inizieremo con la trattazione delle problematiche del \textit{file
+  locking} e poi prenderemo in esame le varie funzionalità avanzate che
+permettono una gestione più sofisticata dell'I/O su file, a partire da quelle
+che consentono di gestire l'accesso contemporaneo a più file esaminando le
+varie modalità alternative di gestire l'I/O per concludere con la gestione dei
+file mappati in memoria e le altre funzioni avanzate che consentono un
+controllo più dettagliato delle modalità di I/O.
+
+
+\section{Il \textit{file locking}}
+\label{sec:file_locking}
+
+\itindbeg{file~locking}
+
+In sez.~\ref{sec:file_shared_access} abbiamo preso in esame le modalità in cui
+un sistema unix-like gestisce l'accesso concorrente ai file da parte di
+processi diversi. In quell'occasione si è visto come, con l'eccezione dei file
+aperti in \textit{append mode}, quando più processi scrivono
+contemporaneamente sullo stesso file non è possibile determinare la sequenza
+in cui essi opereranno.
+
+Questo causa la possibilità di una \textit{race condition}; in generale le
+situazioni più comuni sono due: l'interazione fra un processo che scrive e
+altri che leggono, in cui questi ultimi possono leggere informazioni scritte
+solo in maniera parziale o incompleta; o quella in cui diversi processi
+scrivono, mescolando in maniera imprevedibile il loro output sul file.
+
+In tutti questi casi il \textit{file locking} è la tecnica che permette di
+evitare le \textit{race condition}, attraverso una serie di funzioni che
+permettono di bloccare l'accesso al file da parte di altri processi, così da
+evitare le sovrapposizioni, e garantire la atomicità delle operazioni di
+lettura o scrittura.
+
+
+\subsection{L'\textit{advisory locking}}
+\label{sec:file_record_locking}
+
+La prima modalità di \textit{file locking} che è stata implementata nei
+sistemi unix-like è quella che viene usualmente chiamata \textit{advisory
+  locking},\footnote{Stevens in \cite{APUE} fa riferimento a questo argomento
+  come al \textit{record locking}, dizione utilizzata anche dal manuale delle
+  \acr{glibc}; nelle pagine di manuale si parla di \textit{discrectionary file
+    lock} per \func{fcntl} e di \textit{advisory locking} per \func{flock},
+  mentre questo nome viene usato da Stevens per riferirsi al \textit{file
+    locking} POSIX. Dato che la dizione \textit{record locking} è quantomeno
+  ambigua, in quanto in un sistema Unix non esiste niente che possa fare
+  riferimento al concetto di \textit{record}, alla fine si è scelto di
+  mantenere il nome \textit{advisory locking}.} in quanto sono i singoli
+processi, e non il sistema, che si incaricano di asserire e verificare se
+esistono delle condizioni di blocco per l'accesso ai file. 
+
+Questo significa che le funzioni \func{read} o \func{write} vengono eseguite
+comunque e non risentono affatto della presenza di un eventuale \textit{lock};
+pertanto è sempre compito dei vari processi che intendono usare il
+\textit{file locking}, controllare esplicitamente lo stato dei file condivisi
+prima di accedervi, utilizzando le relative funzioni.
+
+In generale si distinguono due tipologie di \textit{file lock};\footnote{di
+  seguito ci riferiremo sempre ai blocchi di accesso ai file con la
+  nomenclatura inglese di \textit{file lock}, o più brevemente con
+  \textit{lock}, per evitare confusioni linguistiche con il blocco di un
+  processo (cioè la condizione in cui il processo viene posto in stato di
+  \textit{sleep}).} la prima è il cosiddetto \textit{shared lock}, detto anche
+\textit{read lock} in quanto serve a bloccare l'accesso in scrittura su un
+file affinché il suo contenuto non venga modificato mentre lo si legge. Si
+parla appunto di \textsl{blocco condiviso} in quanto più processi possono
+richiedere contemporaneamente uno \textit{shared lock} su un file per
+proteggere il loro accesso in lettura.
+
+La seconda tipologia è il cosiddetto \textit{exclusive lock}, detto anche
+\textit{write lock} in quanto serve a bloccare l'accesso su un file (sia in
+lettura che in scrittura) da parte di altri processi mentre lo si sta
+scrivendo. Si parla di \textsl{blocco esclusivo} appunto perché un solo
+processo alla volta può richiedere un \textit{exclusive lock} su un file per
+proteggere il suo accesso in scrittura.
+
+In Linux sono disponibili due interfacce per utilizzare l'\textit{advisory
+  locking}, la prima è quella derivata da BSD, che è basata sulla funzione
+\func{flock}, la seconda è quella recepita dallo standard POSIX.1 (che è
+derivata dall'interfaccia usata in System V), che è basata sulla funzione
+\func{fcntl}.  I \textit{file lock} sono implementati in maniera completamente
+indipendente nelle due interfacce (in realtà con Linux questo avviene solo
+dalla serie 2.0 dei kernel) che pertanto possono coesistere senza
+interferenze.
+
+Entrambe le interfacce prevedono la stessa procedura di funzionamento: si
+inizia sempre con il richiedere l'opportuno \textit{file lock} (un
+\textit{exclusive lock} per una scrittura, uno \textit{shared lock} per una
+lettura) prima di eseguire l'accesso ad un file.  Se il blocco viene acquisito
+il processo prosegue l'esecuzione, altrimenti (a meno di non aver richiesto un
+comportamento non bloccante) viene posto in stato di \textit{sleep}. Una volta
+finite le operazioni sul file si deve provvedere a rimuovere il blocco.
+
+La situazione delle varie possibilità che si possono verificare è riassunta in
+tab.~\ref{tab:file_file_lock}, dove si sono riportati, a seconda delle varie
+tipologie di blocco già presenti su un file, il risultato che si avrebbe in
+corrispondenza di una ulteriore richiesta da parte di un processo di un blocco
+nelle due tipologie di \textit{file lock} menzionate, con un successo o meno
+della richiesta.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+   \begin{tabular}[c]{|l|c|c|c|}
+    \hline
+    \textbf{Richiesta} & \multicolumn{3}{|c|}{\textbf{Stato del file}}\\
+    \cline{2-4}
+                &Nessun \textit{lock}&\textit{Read lock}&\textit{Write lock}\\
+    \hline
+    \hline
+    \textit{Read lock} & esecuzione & esecuzione & blocco \\
+    \textit{Write lock}& esecuzione & blocco & blocco \\
+    \hline    
+  \end{tabular}
+  \caption{Tipologie di \textit{file locking}.}
+  \label{tab:file_file_lock}
+\end{table}
+
+Si tenga presente infine che il controllo di accesso e la gestione dei
+permessi viene effettuata quando si apre un file, l'unico controllo residuo
+che si può avere riguardo il \textit{file locking} è che il tipo di blocco che
+si vuole ottenere su un file deve essere compatibile con le modalità di
+apertura dello stesso (in lettura per un \textit{read lock} e in scrittura per
+un \textit{write lock}).
+
+%%  Si ricordi che
+%% la condizione per acquisire uno \textit{shared lock} è che il file non abbia
+%% già un \textit{exclusive lock} attivo, mentre per acquisire un
+%% \textit{exclusive lock} non deve essere presente nessun tipo di blocco.
+
+
+\subsection{La funzione \func{flock}} 
+\label{sec:file_flock}
+
+La prima interfaccia per il \textit{file locking}, quella derivata da BSD,
+permette di eseguire un blocco solo su un intero file; la funzione di sistema
+usata per richiedere e rimuovere un \textit{file lock} è \funcd{flock}, ed il
+suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/file.h}
+\fdecl{int flock(int fd, int operation)}
+\fdesc{Applica o rimuove un \textit{file lock}.} 
+}
+
+{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{EINTR}] la funzione è stata interrotta da un segnale
+    nell'attesa dell'acquisizione di un \textit{file lock}.
+  \item[\errcode{EINVAL}] si è specificato un valore non valido
+    per \param{operation}.
+  \item[\errcode{ENOLCK}] il kernel non ha memoria sufficiente per gestire il
+    \textit{file lock}.
+  \item[\errcode{EWOULDBLOCK}] il file ha già un blocco attivo, e si è
+    specificato \const{LOCK\_NB}.
+  \end{errlist}
+  ed inoltre \errval{EBADF} nel suo significato generico.
+}
+\end{funcproto}
+
+La funzione può essere usata per acquisire o rilasciare un \textit{file lock}
+a seconda di quanto specificato tramite il valore dell'argomento
+\param{operation}; questo viene interpretato come maschera binaria, e deve
+essere passato costruendo il valore con un OR aritmetico delle costanti
+riportate in tab.~\ref{tab:file_flock_operation}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{6cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{LOCK\_SH} & Richiede uno \textit{shared lock} sul file.\\ 
+    \constd{LOCK\_EX} & Richiede un \textit{esclusive lock} sul file.\\
+    \constd{LOCK\_UN} & Rilascia il \textit{file lock}.\\
+    \constd{LOCK\_NB} & Impedisce che la funzione si blocchi nella
+                        richiesta di un \textit{file lock}.\\
+    \hline    
+  \end{tabular}
+  \caption{Valori dell'argomento \param{operation} di \func{flock}.}
+  \label{tab:file_flock_operation}
+\end{table}
+
+I primi due valori, \const{LOCK\_SH} e \const{LOCK\_EX} permettono di
+richiedere un \textit{file lock} rispettivamente condiviso o esclusivo, ed
+ovviamente non possono essere usati insieme. Se con essi si specifica anche
+\const{LOCK\_NB} la funzione non si bloccherà qualora il \textit{file lock}
+non possa essere acquisito, ma ritornerà subito con un errore di
+\errcode{EWOULDBLOCK}. Per rilasciare un \textit{file lock} si dovrà invece
+usare direttamente \const{LOCK\_UN}.
+
+Si tenga presente che non esiste una modalità per eseguire atomicamente un
+cambiamento del tipo di blocco (da \textit{shared lock} a \textit{esclusive
+  lock}), il blocco deve essere prima rilasciato e poi richiesto, ed è sempre
+possibile che nel frattempo abbia successo un'altra richiesta pendente,
+facendo fallire la riacquisizione.
+
+Si tenga presente infine che \func{flock} non è supportata per i file
+mantenuti su NFS, in questo caso, se si ha la necessità di utilizzare il
+\textit{file locking}, occorre usare l'interfaccia del \textit{file locking}
+POSIX basata su \func{fcntl} che è in grado di funzionare anche attraverso
+NFS, a condizione ovviamente che sia il client che il server supportino questa
+funzionalità.
+
+La semantica del \textit{file locking} di BSD inoltre è diversa da quella del
+\textit{file locking} POSIX, in particolare per quanto riguarda il
+comportamento dei \textit{file lock} nei confronti delle due funzioni
+\func{dup} e \func{fork}.  Per capire queste differenze occorre descrivere con
+maggiore dettaglio come viene realizzato dal kernel il \textit{file locking}
+per entrambe le interfacce.
+
+In fig.~\ref{fig:file_flock_struct} si è riportato uno schema essenziale
+dell'implementazione del \textit{file locking} in stile BSD su Linux. Il punto
+fondamentale da capire è che un \textit{file lock}, qualunque sia
+l'interfaccia che si usa, anche se richiesto attraverso un file descriptor,
+agisce sempre su di un file; perciò le informazioni relative agli eventuali
+\textit{file lock} sono mantenute dal kernel a livello di \textit{inode}, dato
+che questo è l'unico riferimento in comune che possono avere due processi
+diversi che aprono lo stesso file.
+
+In particolare, come accennato in fig.~\ref{fig:file_flock_struct}, i
+\textit{file lock} sono mantenuti in una \textit{linked list} di strutture
+\kstructd{file\_lock}. La lista è referenziata dall'indirizzo di partenza
+mantenuto dal campo \var{i\_flock} della struttura \kstruct{inode} (per le
+definizioni esatte si faccia riferimento al file \file{include/linux/fs.h} nei
+sorgenti del kernel).  Un bit del campo \var{fl\_flags} di specifica se si
+tratta di un lock in semantica BSD (\constd{FL\_FLOCK}) o POSIX
+(\constd{FL\_POSIX}) o un \textit{file lease} (\constd{FL\_LEASE}, vedi
+sez.~\ref{sec:file_asyncronous_lease}).
+
+\begin{figure}[!htb]
+  \centering
+  \includegraphics[width=12cm]{img/file_flock}
+  \caption{Schema dell'architettura del \textit{file locking}, nel caso
+    particolare del suo utilizzo da parte dalla funzione \func{flock}.}
+  \label{fig:file_flock_struct}
+\end{figure}
+
+La richiesta di un \textit{file lock} prevede una scansione della lista per
+determinare se l'acquisizione è possibile, ed in caso positivo l'aggiunta di
+un nuovo elemento (cioè l'aggiunta di una nuova struttura
+\kstruct{file\_lock}).  Nel caso dei blocchi creati con \func{flock} la
+semantica della funzione prevede che sia \func{dup} che \func{fork} non creino
+ulteriori istanze di un \textit{file lock} quanto piuttosto degli ulteriori
+riferimenti allo stesso. Questo viene realizzato dal kernel secondo lo schema
+di fig.~\ref{fig:file_flock_struct}, associando ad ogni nuovo \textit{file
+  lock} un puntatore alla voce nella \textit{file table} da cui si è richiesto
+il blocco, che così ne identifica il titolare. Il puntatore è mantenuto nel
+campo \var{fl\_file} di \kstruct{file\_lock}, e viene utilizzato solo per i
+\textit{file lock} creati con la semantica BSD.
+
+Questa struttura prevede che, quando si richiede la rimozione di un
+\textit{file lock}, il kernel acconsenta solo se la richiesta proviene da un
+file descriptor che fa riferimento ad una voce nella \textit{file table}
+corrispondente a quella registrata nel blocco.  Allora se ricordiamo quanto
+visto in sez.~\ref{sec:file_dup} e sez.~\ref{sec:file_shared_access}, e cioè
+che i file descriptor duplicati e quelli ereditati in un processo figlio
+puntano sempre alla stessa voce nella \textit{file table}, si può capire
+immediatamente quali sono le conseguenze nei confronti delle funzioni
+\func{dup} e \func{fork}.
+
+Sarà così possibile rimuovere un \textit{file lock} attraverso uno qualunque
+dei file descriptor che fanno riferimento alla stessa voce nella \textit{file
+  table}, anche se questo è diverso da quello con cui lo si è
+creato,\footnote{attenzione, questo non vale se il file descriptor fa
+  riferimento allo stesso file, ma attraverso una voce diversa della
+  \textit{file table}, come accade tutte le volte che si apre più volte lo
+  stesso file.} o se si esegue la rimozione in un processo figlio. Inoltre una
+volta tolto un \textit{file lock} su un file, la rimozione avrà effetto su
+tutti i file descriptor che condividono la stessa voce nella \textit{file
+  table}, e quindi, nel caso di file descriptor ereditati attraverso una
+\func{fork}, anche per processi diversi.
+
+Infine, per evitare che la terminazione imprevista di un processo lasci attivi
+dei \textit{file lock}, quando un file viene chiuso il kernel provvede anche a
+rimuovere tutti i blocchi ad esso associati. Anche in questo caso occorre
+tenere presente cosa succede quando si hanno file descriptor duplicati; in tal
+caso infatti il file non verrà effettivamente chiuso (ed il blocco rimosso)
+fintanto che non viene rilasciata la relativa voce nella \textit{file table};
+e questo avverrà solo quando tutti i file descriptor che fanno riferimento
+alla stessa voce sono stati chiusi.  Quindi, nel caso ci siano duplicati o
+processi figli che mantengono ancora aperto un file descriptor, il
+\textit{file lock} non viene rilasciato.
+
+\subsection{Il \textit{file locking} POSIX}
+\label{sec:file_posix_lock}
+
+La seconda interfaccia per l'\textit{advisory locking} disponibile in Linux è
+quella standardizzata da POSIX, basata sulla funzione di sistema
+\func{fcntl}. Abbiamo già trattato questa funzione nelle sue molteplici
+possibilità di utilizzo in sez.~\ref{sec:file_fcntl_ioctl}. Quando la si
+impiega per il \textit{file locking} essa viene usata solo secondo il seguente
+prototipo:
+
+\begin{funcproto}{
+\fhead{fcntl.h}
+\fdecl{int fcntl(int fd, int cmd, struct flock *lock)}
+\fdesc{Applica o rimuove un \textit{file lock}.} 
+}
+
+{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{EACCES}] l'operazione è proibita per la presenza di
+      \textit{file lock} da parte di altri processi.
+    \item[\errcode{EDEADLK}] si è richiesto un \textit{lock} su una regione
+      bloccata da un altro processo che è a sua volta in attesa dello sblocco
+      di un \textit{lock} mantenuto dal processo corrente; si avrebbe pertanto
+      un \textit{deadlock}. Non è garantito che il sistema riconosca sempre
+      questa situazione.
+    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
+      di poter acquisire un \textit{file lock}.
+    \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}, o il protocollo per il blocco remoto è fallito.
+  \end{errlist}
+  ed inoltre \errval{EBADF}, \errval{EFAULT} nel loro significato generico.}
+\end{funcproto}
+
+Al contrario di quanto avviene con l'interfaccia basata su \func{flock} con
+\func{fcntl} è possibile bloccare anche delle singole sezioni di un file, fino
+al singolo byte. Inoltre la funzione permette di ottenere alcune informazioni
+relative agli eventuali blocchi preesistenti.  Per poter fare tutto questo la
+funzione utilizza come terzo argomento una apposita struttura \struct{flock}
+(la cui definizione è riportata in fig.~\ref{fig:struct_flock}) nella quale
+inserire tutti i dati relativi ad un determinato blocco. Si tenga presente poi
+che un \textit{file lock} fa sempre riferimento ad una regione, per cui si
+potrà avere un conflitto anche se c'è soltanto una sovrapposizione parziale
+con un'altra regione bloccata.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{0.90\textwidth}
+    \includestruct{listati/flock.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{flock}, usata da \func{fcntl} per il
+    \textit{file locking}.}
+  \label{fig:struct_flock}
+\end{figure}
+
+I primi tre campi della struttura, \var{l\_whence}, \var{l\_start} e
+\var{l\_len}, servono a specificare la sezione del file a cui fa riferimento
+il blocco: \var{l\_start} specifica il byte di partenza, \var{l\_len} la
+lunghezza della sezione e infine \var{l\_whence} imposta il riferimento da cui
+contare \var{l\_start}. Il valore di \var{l\_whence} segue la stessa semantica
+dell'omonimo argomento di \func{lseek}, coi tre possibili valori
+\const{SEEK\_SET}, \const{SEEK\_CUR} e \const{SEEK\_END}, (si vedano le
+relative descrizioni in tab.~\ref{tab:lseek_whence_values}).
+
+Si tenga presente che un \textit{file lock} può essere richiesto anche per una
+regione al di là della corrente fine del file, così che una eventuale
+estensione dello stesso resti coperta dal blocco. Inoltre se si specifica un
+valore nullo per \var{l\_len} il blocco si considera esteso fino alla
+dimensione massima del file; in questo modo è possibile bloccare una qualunque
+regione a partire da un certo punto fino alla fine del file, coprendo
+automaticamente quanto eventualmente aggiunto in coda allo stesso.
+
+Lo standard POSIX non richiede che \var{l\_len} sia positivo, ed a partire dal
+kernel 2.4.21 è possibile anche indicare valori di \var{l\_len} negativi, in
+tal caso l'intervallo coperto va da \var{l\_start}$+$\var{l\_len} a
+\var{l\_start}$-1$, mentre per un valore positivo l'intervallo va da
+\var{l\_start} a \var{l\_start}$+$\var{l\_len}$-1$. Si può però usare un
+valore negativo soltanto se l'inizio della regione indicata non cade prima
+dell'inizio del file, mentre come accennato con un valore positivo  si
+può anche indicare una regione che eccede la dimensione corrente del file.
+
+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}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{F\_RDLCK} & Richiede un blocco condiviso (\textit{read lock}).\\
+    \constd{F\_WRLCK} & Richiede un blocco esclusivo (\textit{write lock}).\\
+    \constd{F\_UNLCK} & Richiede l'eliminazione di un \textit{file lock}.\\
+    \hline    
+  \end{tabular}
+  \caption{Valori possibili per il campo \var{l\_type} di \struct{flock}.}
+  \label{tab:file_flock_type}
+\end{table}
+
+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_ioctl},
+specifica l'azione da compiere; i valori utilizzabili relativi al \textit{file
+  locking} sono tre:
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\constd{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[\constd{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[\constd{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 \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 \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 \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}. In questo caso nella figura si sono
+evidenziati solo i campi di \kstructd{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 all'\textit{inode}, solo che in questo caso la titolarità non
+viene identificata con il riferimento ad una voce nella \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 \textit{linked
+    list} delle strutture \kstruct{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}.
+
+Con i \textit{file lock} POSIX 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
+si 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:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -r Flock.c}
+Lock acquired
+\end{Console}
+%$
+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:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -w Flock.c}
+Failed lock: Resource temporarily unavailable
+\end{Console}
+%$
+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:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -w -s0 -l10 Flock.c}
+Failed lock: Resource temporarily unavailable
+\end{Console}
+%$
+se invece blocchiamo una regione con: 
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -r -s0 -l10 Flock.c}
+Lock acquired
+\end{Console}
+%$
+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:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -w -s5 -l15  Flock.c}
+Failed lock: Resource temporarily unavailable
+\end{Console}
+%$
+ed il blocco viene rifiutato, ma se invece si richiede una regione distinta
+avremo che:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -w -s11 -l15  Flock.c}
+Lock acquired
+\end{Console}
+%$
+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:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -r -s10 -l20 Flock.c}
+Failed lock: Resource temporarily unavailable
+\end{Console}
+%$
+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:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -r -b -s0 -l10 Flock.c} Lock acquired
+\end{Console}
+%$
+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:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -w -s0 -l10 Flock.c}
+\end{Console}
+%$
+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:
+
+\begin{Console}
+[piccardi@gont sources]$ \textbf{./flock -w -s0 -l10 Flock.c}
+Lock acquired
+\end{Console}
+%$
+
+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:
+
+\begin{Console}
+[root@gont sources]# \textbf{./flock -f -w Flock.c}
+Lock acquired
+\end{Console}
+%$
+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 che utilizza la
+funzione \funcd{lockf},\footnote{la funzione è ripresa da System V e per
+  poterla utilizzare è richiesta che siano definite le opportune macro, una
+  fra \macro{\_BSD\_SOURCE} o \macro{\_SVID\_SOURCE}, oppure
+  \macro{\_XOPEN\_SOURCE} ad un valore di almeno 500, oppure
+  \macro{\_XOPEN\_SOURCE} e \macro{\_XOPEN\_SOURCE\_EXTENDED}.} il cui
+prototipo è:
+
+\begin{funcproto}{
+\fhead{unistd.h}
+\fdecl{int lockf(int fd, int cmd, off\_t len)}
+\fdesc{Applica, controlla o rimuove un \textit{file lock}.} 
+}
+
+{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{EAGAIN}] il file è bloccato, e si sono richiesti
+    \const{F\_TLOCK} o \const{F\_TEST} (in alcuni casi può dare anche
+    \errcode{EACCESS}.
+  \item[\errcode{EBADF}] \param{fd} non è un file descriptor aperto o si sono
+    richiesti \const{F\_LOCK} o \const{F\_TLOCK} ma il file non è scrivibile.
+  \item[\errcode{EINVAL}] si è usato un valore non valido per \param{cmd}.
+  \end{errlist}
+  ed inoltre \errcode{EDEADLK} e \errcode{ENOLCK} con lo stesso significato
+  che hanno con \func{fcntl}.
+}
+\end{funcproto}
+  
+La funzione opera sul file indicato dal file descriptor \param{fd}, che deve
+essere aperto in scrittura, perché utilizza soltanto \textit{lock}
+esclusivi. La sezione di file bloccata viene controllata dal valore
+di \param{len}, che indica la lunghezza della stessa, usando come riferimento
+la posizione corrente sul file. La sezione effettiva varia a secondo del
+segno, secondo lo schema illustrato in fig.~\ref{fig:file_lockf_boundary}, se
+si specifica un valore nullo il file viene bloccato a partire dalla posizione
+corrente fino alla sua fine presente o futura (nello schema corrisponderebbe
+ad un valore infinito positivo).
+
+\begin{figure}[!htb] 
+  \centering
+  \includegraphics[width=10cm]{img/lockf_boundary}
+  \caption{Schema della sezione di file bloccata con \func{lockf}.}
+  \label{fig:file_lockf_boundary}
+\end{figure}
+
+Il comportamento della funzione viene controllato dal valore
+dell'argomento \param{cmd}, che specifica quale azione eseguire, i soli valori
+consentiti sono i seguenti:
+
+\begin{basedescript}{\desclabelwidth{2.0cm}}
+\item[\constd{F\_LOCK}] Richiede un \textit{lock} esclusivo sul file, e blocca
+  il processo chiamante se, anche parzialmente, la sezione indicata si
+  sovrappone ad una che è già stata bloccata da un altro processo; in caso di
+  sovrapposizione con un altro blocco già ottenuto le sezioni vengono unite.
+\item[\constd{F\_TLOCK}] Richiede un \textit{exclusive lock}, in maniera
+  identica a \const{F\_LOCK}, ma in caso di indisponibilità non blocca il
+  processo restituendo un errore di \errval{EAGAIN}.
+\item[\constd{F\_ULOCK}] Rilascia il blocco sulla sezione indicata, questo può
+  anche causare la suddivisione di una sezione bloccata in precedenza nelle
+  due parti eccedenti nel caso si sia indicato un intervallo più limitato.
+\item[\constd{F\_TEST}] Controlla la presenza di un blocco sulla sezione di
+  file indicata, \func{lockf} ritorna $0$ se la sezione è libera o bloccata
+  dal processo stesso, o $-1$ se è bloccata da un altro processo, nel qual
+  caso \var{errno} assume il valore \errval{EAGAIN} (ma su alcuni sistemi può
+  essere restituito anche \errval{EACCESS}).
+\end{basedescript}
+
+La funzione è semplicemente una diversa interfaccia al \textit{file locking}
+POSIX ed è realizzata utilizzando \func{fcntl}; pertanto la semantica delle
+operazioni è la stessa di quest'ultima e quindi la funzione presenta lo stesso
+comportamento riguardo gli effetti della chiusura dei file, ed il
+comportamento sui file duplicati e nel passaggio attraverso \func{fork} ed
+\func{exec}. Per questo stesso motivo la funzione non è equivalente a
+\func{flock} e può essere usata senza interferenze insieme a quest'ultima.
+
+% TODO trattare i POSIX file-private lock introdotti con il 3.15, 
+% vedi http://lwn.net/Articles/586904/ correlato:
+% http://www.samba.org/samba/news/articles/low_point/tale_two_stds_os2.html 
+
+\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 \acr{sgid} dei permessi dei file. 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 \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:filesystem_mounting}, 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 (vedi
+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
+\textit{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.
+
+Si tenga conto infine che su Linux l'implementazione corrente del
+\textit{mandatory locking} è difettosa e soffre di una \textit{race
+  condition}, per cui una scrittura con \func{write} che si sovrapponga alla
+richiesta di un \textit{read lock} può modificare i dati anche dopo che questo
+è stato ottenuto, ed una lettura con \func{read} può restituire dati scritti
+dopo l'ottenimento di un \textit{write lock}. Lo stesso tipo di problema si
+può presentare anche con l'uso di file mappati in memoria; pertanto allo stato
+attuale delle cose è sconsigliabile fare affidamento sul \textit{mandatory
+  locking}.
+
+% TODO il supporto è stato reso opzionale nel 4.5, verrà eliminato nel futuro
+% (vedi http://lwn.net/Articles/667210/)
+
+\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
+sez.~\ref{sec:file_unix_interface} e sez.~\ref{sec: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} \textit{system call}, che in certi casi le
+funzioni di I/O eseguite su un file descriptor possono bloccarsi
+indefinitamente. Questo non avviene mai per i file normali, per i quali le
+funzioni di lettura e scrittura ritornano sempre subito, ma può avvenire per
+alcuni file di dispositivo, come ad esempio una seriale o un terminale, o con
+l'uso di file descriptor collegati a meccanismi di intercomunicazione come le
+\textit{pipe} (vedi sez.~\ref{sec:ipc_unix}) ed i socket (vedi
+sez.~\ref{sec:sock_socket_def}). In casi come questi ad esempio una operazione
+di lettura potrebbe bloccarsi se non ci sono dati disponibili sul descrittore
+su cui la si sta effettuando.
+
+Questo comportamento è alla radice di una delle problematiche più comuni che
+ci si trova ad affrontare nella gestione delle operazioni di I/O: la necessità
+di operare su più file descriptor eseguendo funzioni che possono bloccarsi
+indefinitamente senza che sia possibile prevedere quando questo può
+avvenire. Un caso classico è quello di un server di rete (tratteremo la
+problematica in dettaglio nella seconda parte della guida) in attesa di dati
+in ingresso prevenienti da vari client.
+
+In un caso di questo tipo, se si andasse ad operare sui vari file descriptor
+aperti uno dopo l'altro, potrebbe accadere di restare bloccati nell'eseguire
+una lettura su uno di quelli che non è ``\textsl{pronto}'', quando ce ne
+potrebbe essere un altro con dati disponibili. Questo comporta nel migliore
+dei casi una operazione ritardata inutilmente nell'attesa del completamento di
+quella bloccata, mentre nel peggiore dei casi, quando la conclusione
+dell'operazione bloccata dipende da quanto si otterrebbe dal file descriptor
+``\textsl{disponibile}'', si potrebbe addirittura arrivare ad un
+\textit{deadlock}.
+
+\itindbeg{polling}
+
+Abbiamo già accennato in sez.~\ref{sec:file_open_close} che è possibile
+prevenire questo tipo di comportamento delle funzioni di I/O aprendo un file
+in \textsl{modalità non-bloccante}, attraverso l'uso del flag
+\const{O\_NONBLOCK} nella chiamata di \func{open}. In questo caso le funzioni
+di lettura o scrittura eseguite sul file che si sarebbero bloccate ritornano
+immediatamente, restituendo l'errore \errcode{EAGAIN}.  L'utilizzo di questa
+modalità di I/O permette di risolvere il problema controllando a turno i vari
+file descriptor, in un ciclo in cui si ripete l'accesso fintanto che esso non
+viene garantito. Ovviamente questa tecnica, detta \textit{polling}, è
+estremamente inefficiente: si tiene costantemente impiegata la CPU solo per
+eseguire in continuazione delle \textit{system call} che nella gran parte dei
+casi falliranno.
+
+\itindend{polling}
+
+É appunto per superare questo problema è stato introdotto il concetto di
+\textit{I/O multiplexing}, una nuova modalità per la gestione dell'I/O che
+consente di tenere sotto controllo più file descriptor in contemporanea,
+permettendo di bloccare un processo quando le operazioni di lettura o
+scrittura non sono immediatamente effettuabili, e di riprenderne l'esecuzione
+una volta che almeno una di quelle che erano state richieste diventi
+possibile, in modo da poterla eseguire con la sicurezza di non restare
+bloccati.
+
+Dato che, come abbiamo già accennato, per i normali file su disco non si ha
+mai un accesso bloccante, l'uso più comune delle funzioni che esamineremo nei
+prossimi paragrafi è per i server di rete, in cui esse vengono utilizzate per
+tenere sotto controllo dei socket; pertanto ritorneremo su di esse con
+ulteriori dettagli e qualche esempio di utilizzo concreto in
+sez.~\ref{sec:TCP_sock_multiplexing}.
+
+
+\subsection{Le funzioni \func{select} e \func{pselect}}
+\label{sec:file_select}
+
+Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
+  multiplexing} è stato BSD, con la funzione \funcd{select} che è apparsa in
+BSD4.2 ed è stata standardizzata in BSD4.4, in seguito è stata portata su
+tutti i sistemi che supportano i socket, compreso le varianti di System V ed
+inserita in POSIX.1-2001; il suo prototipo è:\footnote{l'header
+  \texttt{sys/select.h} è stato introdotto con POSIX.1-2001, è ed presente con
+  le \acr{glibc} a partire dalla versione 2.0, in precedenza, con le
+  \acr{libc4} e le \acr{libc5}, occorreva includere \texttt{sys/time.h},
+  \texttt{sys/types.h} e \texttt{unistd.h}.}
+
+\begin{funcproto}{
+\fhead{sys/select.h}
+\fdecl{int select(int ndfs, fd\_set *readfds, fd\_set *writefds, fd\_set
+    *exceptfds, \\
+\phantom{int select(}struct timeval *timeout)}
+\fdesc{Attende che uno fra i file descriptor degli insiemi specificati diventi
+  attivo.} 
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori: 
+  \begin{errlist}
+  \item[\errcode{EBADF}] si è specificato un file descriptor non valido
+    (chiuso o con errori) in uno degli insiemi.
+  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+  \item[\errcode{EINVAL}] si è specificato per \param{ndfs} un valore negativo
+    o un valore non valido per \param{timeout}.
+  \end{errlist}
+  ed inoltre \errval{ENOMEM} nel suo significato generico.}
+\end{funcproto}
+
+La funzione mette il processo in stato di \textit{sleep} (vedi
+tab.~\ref{tab:proc_proc_states}) fintanto che almeno uno dei file descriptor
+degli insiemi specificati (\param{readfds}, \param{writefds} e
+\param{exceptfds}), non diventa attivo, per un tempo massimo specificato da
+\param{timeout}.
+
+\itindbeg{file~descriptor~set} 
+
+Per specificare quali file descriptor si intende selezionare la funzione usa
+un particolare oggetto, il \textit{file descriptor set}, identificato dal tipo
+\typed{fd\_set}, che serve ad identificare un insieme di file descriptor, in
+maniera analoga a come un \textit{signal set} (vedi sez.~\ref{sec:sig_sigset})
+identifica un insieme di segnali. Per la manipolazione di questi \textit{file
+  descriptor set} si possono usare delle opportune macro di preprocessore:
+
+{\centering
+\vspace{3pt}
+\begin{funcbox}{
+\fhead{sys/select.h}
+\fdecl{void \macrod{FD\_ZERO}(fd\_set *set)}
+\fdesc{Inizializza l'insieme (vuoto).} 
+\fdecl{void \macrod{FD\_SET}(int fd, fd\_set *set)}
+\fdesc{Inserisce il file descriptor \param{fd} nell'insieme.} 
+\fdecl{void \macrod{FD\_CLR}(int fd, fd\_set *set)}
+\fdesc{Rimuove il file descriptor \param{fd} dall'insieme.} 
+\fdecl{int \macrod{FD\_ISSET}(int fd, fd\_set *set)}
+\fdesc{Controlla se il file descriptor \param{fd} è nell'insieme.} 
+}
+\end{funcbox}}
+
+
+In genere un \textit{file descriptor set} può contenere fino ad un massimo di
+\macrod{FD\_SETSIZE} file descriptor.  Questo valore in origine corrispondeva
+al limite per il numero massimo di file aperti (ad esempio in Linux, fino alla
+serie 2.0.x, c'era un limite di 256 file per processo), ma da quando, nelle
+versioni più recenti del kernel, questo limite è stato rimosso, esso indica le
+dimensioni massime dei numeri usati nei \textit{file descriptor set}, ed il
+suo valore, secondo lo standard POSIX 1003.1-2001, è definito in
+\headfile{sys/select.h}, ed è pari a 1024.
+
+Si tenga presente che i \textit{file descriptor set} devono sempre essere
+inizializzati con \macro{FD\_ZERO}; passare a \func{select} un valore non
+inizializzato può dar luogo a comportamenti non prevedibili. Allo stesso modo
+usare \macro{FD\_SET} o \macro{FD\_CLR} con un file descriptor il cui valore
+eccede \macro{FD\_SETSIZE} può dare luogo ad un comportamento indefinito.
+
+La funzione richiede di specificare tre insiemi distinti di file descriptor;
+il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
+effettuare una lettura,\footnote{per essere precisi la funzione ritornerà in
+  tutti i casi in cui la successiva esecuzione di \func{read} risulti non
+  bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo,
+\param{writefds}, per verificare la possibilità di effettuare una scrittura ed
+il terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni come i
+dati urgenti su un socket, (vedi sez.~\ref{sec:TCP_urgent_data}).
+
+Dato che in genere non si tengono mai sotto controllo fino a
+\macro{FD\_SETSIZE} file contemporaneamente, la funzione richiede di
+specificare qual è il valore più alto fra i file descriptor indicati nei tre
+insiemi precedenti. Questo viene fatto per efficienza, per evitare di passare
+e far controllare al kernel una quantità di memoria superiore a quella
+necessaria. Questo limite viene indicato tramite l'argomento \param{ndfs}, che
+deve corrispondere al valore massimo aumentato di uno. Si ricordi infatti che
+i file descriptor sono numerati progressivamente a partire da zero, ed il
+valore indica il numero più alto fra quelli da tenere sotto controllo,
+dimenticarsi di aumentare di uno il valore di \param{ndfs} è un errore comune.
+
+Infine l'argomento \param{timeout}, espresso con il puntatore ad una struttura
+di tipo \struct{timeval} (vedi fig.~\ref{fig:sys_timeval_struct}) specifica un
+tempo massimo di attesa prima che la funzione ritorni; se impostato a
+\val{NULL} la funzione attende indefinitamente. Si può specificare anche un
+tempo nullo (cioè una struttura \struct{timeval} con i campi impostati a
+zero), qualora si voglia semplicemente controllare lo stato corrente dei file
+descriptor, e così può essere utilizzata eseguire il \textit{polling} su un
+gruppo di file descriptor. Usare questo argomento con tutti i \textit{file
+  descriptor set} vuoti è un modo portabile, disponibile anche su sistemi in
+cui non sono disponibili le funzioni avanzate di sez.~\ref{sec:sig_timer_adv},
+per tenere un processo in stato di \textit{sleep} con precisioni inferiori al
+secondo.
+
+In caso di successo la funzione restituisce il numero di file descriptor
+pronti, seguendo il comportamento previsto dallo standard
+POSIX.1-2001,\footnote{si tenga però presente che esistono alcune versioni di
+  Unix che non si comportano in questo modo, restituendo un valore positivo
+  generico.}  e ciascun insieme viene sovrascritto per indicare quali sono i
+file descriptor pronti per le operazioni ad esso relative, in modo da poterli
+controllare con \macro{FD\_ISSET}.  Se invece scade il tempo indicato
+da \param{timout} viene restituito un valore nullo e i \textit{file descriptor
+  set} non vengono modificati. In caso di errore la funzione restituisce $-1$, i
+valori dei tre insiemi e di \param{timeout} sono indefiniti e non si può fare
+nessun affidamento sul loro contenuto; nelle versioni più recenti della
+funzione invece i \textit{file descriptor set} non vengono modificati anche in
+caso di errore.
+
+Si tenga presente infine che su Linux, in caso di programmazione
+\textit{multi-thread} se un file descriptor viene chiuso in un altro
+\textit{thread} rispetto a quello in cui si sta usando \func{select}, questa
+non subisce nessun effetto. In altre varianti di sistemi unix-like invece
+\func{select} ritorna indicando che il file descriptor è pronto, con
+conseguente possibile errore nel caso lo si usi senza che sia stato
+riaperto. Lo standard non prevede niente al riguardo e non si deve dare per
+assunto nessuno dei due comportamenti se si vogliono scrivere programmi
+portabili.
+
+\itindend{file~descriptor~set}
+
+Una volta ritornata la funzione, si potrà controllare quali sono i file
+descriptor pronti, ed operare su di essi. Si tenga presente però che
+\func{select} fornisce solo di un suggerimento, esistono infatti condizioni in
+cui \func{select} può riportare in maniera spuria che un file descriptor è
+pronto, ma l'esecuzione di una operazione di I/O si bloccherebbe: ad esempio
+con Linux questo avviene quando su un socket arrivano dei dati che poi vengono
+scartati perché corrotti (ma sono possibili pure altri casi); in tal caso pur
+risultando il relativo file descriptor pronto in lettura una successiva
+esecuzione di una \func{read} si bloccherebbe. Per questo motivo quando si usa
+l'\textit{I/O multiplexing} è sempre raccomandato l'uso delle funzioni di
+lettura e scrittura in modalità non bloccante.
+
+Su Linux quando la \textit{system call} \func{select} viene interrotta da un
+segnale modifica il valore nella struttura puntata da \param{timeout},
+impostandolo al tempo restante. In tal caso infatti si ha un errore di
+\errcode{EINTR} ed occorre rilanciare la funzione per proseguire l'attesa, ed
+in questo modo non è necessario ricalcolare tutte le volte il tempo
+rimanente. Questo può causare problemi di portabilità sia quando si usa codice
+scritto su Linux che legge questo valore, sia quando si usano programmi
+scritti per altri sistemi che non dispongono di questa caratteristica e
+ricalcolano \param{timeout} tutte le volte. In genere questa caratteristica è
+disponibile nei sistemi che derivano da System V e non è disponibile per
+quelli che derivano da BSD; lo standard POSIX.1-2001 non permette questo
+comportamento e per questo motivo le \acr{glibc} nascondono il comportamento
+passando alla \textit{system call} una copia dell'argomento \param{timeout}.
+
+Uno dei problemi che si presentano con l'uso di \func{select} è che il suo
+comportamento dipende dal valore del file descriptor che si vuole tenere sotto
+controllo.  Infatti il kernel riceve con \param{ndfs} un limite massimo per
+tale valore, e per capire quali sono i file descriptor da tenere sotto
+controllo dovrà effettuare una scansione su tutto l'intervallo, che può anche
+essere molto ampio anche se i file descriptor sono solo poche unità; tutto ciò
+ha ovviamente delle conseguenze ampiamente negative per le prestazioni.
+
+Inoltre c'è anche il problema che il numero massimo dei file che si possono
+tenere sotto controllo, la funzione è nata quando il kernel consentiva un
+numero massimo di 1024 file descriptor per processo, adesso che il numero può
+essere arbitrario si viene a creare una dipendenza del tutto artificiale dalle
+dimensioni della struttura \type{fd\_set}, che può necessitare di essere
+estesa, con ulteriori perdite di prestazioni. 
+
+Lo standard POSIX è rimasto a lungo senza primitive per l'\textit{I/O
+  multiplexing}, introdotto solo con le ultime revisioni dello standard (POSIX
+1003.1g-2000 e POSIX 1003.1-2001). La scelta è stata quella di seguire
+l'interfaccia creata da BSD, ma prevede che tutte le funzioni ad esso relative
+vengano dichiarate nell'header \headfiled{sys/select.h}, che sostituisce i
+precedenti, ed inoltre aggiunge a \func{select} una nuova funzione
+\funcd{pselect},\footnote{il supporto per lo standard POSIX 1003.1-2001, ed
+  l'header \headfile{sys/select.h}, compaiono in Linux a partire dalle
+  \acr{glibc} 2.1. Le \acr{libc4} e \acr{libc5} non contengono questo header,
+  le \acr{glibc} 2.0 contengono una definizione sbagliata di \func{psignal},
+  senza l'argomento \param{sigmask}, la definizione corretta è presente dalle
+  \acr{glibc} 2.1-2.2.1 se si è definito \macro{\_GNU\_SOURCE} e nelle
+  \acr{glibc} 2.2.2-2.2.4 se si è definito \macro{\_XOPEN\_SOURCE} con valore
+  maggiore di 600.} il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/select.h}
+\fdecl{int pselect(int n, fd\_set *readfds, fd\_set *writefds, 
+  fd\_set *exceptfds, \\ 
+\phantom{int pselect(}struct timespec *timeout, sigset\_t *sigmask)}
+\fdesc{Attende che uno dei file descriptor degli insiemi specificati diventi
+  attivo.} 
+}
+{La funzione ritorna il numero (anche nullo) di file descriptor che sono
+  attivi in caso di successo e $-1$ per un errore, nel qual caso \var{errno}
+  assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato in uno
+    degli insiemi.
+  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+  \item[\errcode{EINVAL}] si è specificato per \param{ndfs} un valore negativo
+    o un valore non valido per \param{timeout}.
+   \end{errlist}
+   ed inoltre \errval{ENOMEM} nel suo significato generico.
+}
+\end{funcproto}
+
+La funzione è sostanzialmente identica a \func{select}, solo che usa una
+struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timespec_struct}) per
+indicare con maggiore precisione il timeout e non ne aggiorna il valore in
+caso di interruzione. In realtà anche in questo caso la \textit{system call}
+di Linux aggiorna il valore al tempo rimanente, ma la funzione fornita dalle
+\acr{glibc} modifica questo comportamento passando alla \textit{system call}
+una variabile locale, in modo da mantenere l'aderenza allo standard POSIX che
+richiede che il valore di \param{timeout} non sia modificato. 
+
+Rispetto a \func{select} la nuova funzione prende un argomento
+aggiuntivo \param{sigmask}, un puntatore ad una maschera di segnali (si veda
+sez.~\ref{sec:sig_sigmask}).  Nell'esecuzione la maschera dei segnali corrente
+viene sostituita da quella così indicata immediatamente prima di eseguire
+l'attesa, e viene poi ripristinata al ritorno della funzione. L'uso
+di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
+\textit{race condition} quando oltre alla presenza di dati sui file descriptor
+come nella \func{select} ordinaria, ci si deve porre in attesa anche
+dell'arrivo di un segnale.
+
+Come abbiamo visto in sez.~\ref{sec:sig_example} la tecnica classica per
+rilevare l'arrivo di un segnale è quella di utilizzare il gestore per
+impostare una variabile globale e controllare questa nel corpo principale del
+programma; abbiamo visto in quell'occasione come questo lasci spazio a
+possibili \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 \textit{race condition}, perché se il segnale arriva prima
+della chiamata a \func{select}, questa non verrà interrotta, e la ricezione
+del segnale non sarà rilevata.
+
+Per questo è stata introdotta \func{pselect} che attraverso l'argomento
+\param{sigmask} permette di riabilitare la ricezione il segnale
+contestualmente all'esecuzione della funzione,\footnote{in Linux però, fino al
+  kernel 2.6.16, non era presente la relativa \textit{system call}, e la
+  funzione era implementata nelle \acr{glibc} attraverso \func{select} (vedi
+  \texttt{man select\_tut}) per cui la possibilità di \textit{race condition}
+  permaneva; in tale situazione si può ricorrere ad una soluzione alternativa,
+  chiamata \itindex{self-pipe~trick} \textit{self-pipe trick}, che consiste
+  nell'aprire una \textit{pipe} (vedi sez.~\ref{sec:ipc_pipes}) ed usare
+  \func{select} sul capo in lettura della stessa; si può indicare l'arrivo di
+  un segnale scrivendo sul capo in scrittura all'interno del gestore dello
+  stesso; in questo modo anche se il segnale va perso prima della chiamata di
+  \func{select} questa lo riconoscerà comunque dalla presenza di dati sulla
+  \textit{pipe}.} ribloccandolo non appena essa ritorna, così che il
+precedente codice potrebbe essere riscritto nel seguente modo:
+\includecodesnip{listati/pselect_norace.c} 
+in questo caso utilizzando \var{oldmask} durante l'esecuzione di
+\func{pselect} la ricezione del segnale sarà abilitata, ed in caso di
+interruzione si potranno eseguire le relative operazioni.
+
+
+\subsection{Le funzioni \func{poll} e \func{ppoll}}
+\label{sec:file_poll}
+
+Nello sviluppo di System V, invece di utilizzare l'interfaccia di
+\func{select}, che è una estensione tipica di BSD, è stata introdotta una
+interfaccia completamente diversa, basata sulla funzione di sistema
+\funcd{poll},\footnote{la funzione è prevista dallo standard XPG4, ed è stata
+  introdotta in Linux come \textit{system call} a partire dal kernel 2.1.23 ed
+  inserita nelle \acr{libc} 5.4.28, originariamente l'argomento \param{nfds}
+  era di tipo \ctyp{unsigned int}, la funzione è stata inserita nello standard
+  POSIX.1-2001 in cui è stato introdotto il tipo nativo \typed{nfds\_t}.} il
+cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/poll.h}
+\fdecl{int poll(struct pollfd *ufds, nfds\_t nfds, int timeout)}
+\fdesc{Attende un cambiamento di stato su un insieme di file
+  descriptor.} 
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori: 
+  \begin{errlist}
+  \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato in uno
+    degli insiemi.
+  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+  \item[\errcode{EINVAL}] il valore di \param{nfds} eccede il limite
+    \const{RLIMIT\_NOFILE}.
+  \end{errlist}
+  ed inoltre \errval{EFAULT} e \errval{ENOMEM} nel loro significato generico.}
+\end{funcproto}
+
+La funzione permette di tenere sotto controllo contemporaneamente \param{ndfs}
+file descriptor, specificati attraverso il puntatore \param{ufds} ad un
+vettore di strutture \struct{pollfd}.  Come con \func{select} si può
+interrompere l'attesa dopo un certo tempo, questo deve essere specificato con
+l'argomento \param{timeout} in numero di millisecondi: un valore negativo
+indica un'attesa indefinita, mentre un valore nullo comporta il ritorno
+immediato, e può essere utilizzato per impiegare \func{poll} in modalità
+\textsl{non-bloccante}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{0.90\textwidth}
+    \includestruct{listati/pollfd.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{pollfd}, utilizzata per specificare le
+    modalità di controllo di un file descriptor alla funzione \func{poll}.}
+  \label{fig:file_pollfd}
+\end{figure}
+
+Per ciascun file da controllare deve essere inizializzata una struttura
+\struct{pollfd} nel vettore indicato dall'argomento \param{ufds}.  La
+struttura, la cui definizione è riportata in fig.~\ref{fig:file_pollfd},
+prevede tre campi: in \var{fd} deve essere indicato il numero del file
+descriptor da controllare, in \var{events} deve essere specificata una
+maschera binaria di flag che indichino il tipo di evento che si vuole
+controllare, mentre in \var{revents} il kernel restituirà il relativo
+risultato. 
+
+Usando un valore negativo per \param{fd} la corrispondente struttura sarà
+ignorata da \func{poll} ed il campo \var{revents} verrà azzerato, questo
+consente di eliminare temporaneamente un file descriptor dalla lista senza
+dover modificare il vettore \param{ufds}. Dato che i dati in ingresso sono del
+tutto indipendenti da quelli in uscita (che vengono restituiti in
+\var{revents}) non è necessario reinizializzare tutte le volte il valore delle
+strutture \struct{pollfd} a meno di non voler cambiare qualche condizione.
+
+Le costanti che definiscono i valori relativi ai bit usati nelle maschere
+binarie dei campi \var{events} e \var{revents} sono riportate in
+tab.~\ref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono
+suddivise in tre gruppi principali, nel primo gruppo si sono indicati i bit
+utilizzati per controllare l'attività in ingresso, nel secondo quelli per
+l'attività in uscita, infine il terzo gruppo contiene dei valori che vengono
+utilizzati solo nel campo \var{revents} per notificare delle condizioni di
+errore.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Flag}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{POLLIN}    & È possibile la lettura.\\
+    \constd{POLLRDNORM}& Sono disponibili in lettura dati normali.\\ 
+    \constd{POLLRDBAND}& Sono disponibili in lettura dati prioritari.\\
+    \constd{POLLPRI}   & È possibile la lettura di dati urgenti.\\ 
+    \hline
+    \constd{POLLOUT}   & È possibile la scrittura immediata.\\
+    \constd{POLLWRNORM}& È possibile la scrittura di dati normali.\\ 
+    \constd{POLLWRBAND}& È possibile la scrittura di dati prioritari.\\
+    \hline
+    \constd{POLLERR}   & C'è una condizione di errore.\\
+    \constd{POLLHUP}   & Si è verificato un hung-up.\\
+    \constd{POLLRDHUP} & Si è avuta una \textsl{half-close} su un
+                        socket.\footnotemark\\ 
+    \constd{POLLNVAL}  & Il file descriptor non è aperto.\\
+    \hline
+    \constd{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 \textit{half-close}
+  (\textsl{mezza chiusura}) su cui torneremo con maggiori dettagli in
+  sez.~\ref{sec:TCP_shutdown}.}
+
+Il valore \const{POLLMSG} non viene utilizzato ed è definito solo per
+compatibilità con l'implementazione di System V che usa i cosiddetti
+``\textit{stream}''. Si tratta di una interfaccia specifica di SysV non
+presente in Linux, che non ha nulla a che fare con gli \textit{stream} delle
+librerie standard del C visti in sez.~\ref{sec:file_stream}. Da essa derivano
+i nomi di alcune costanti poiché per quegli \textit{stream} sono definite tre
+classi di dati: \textsl{normali}, \textit{prioritari} ed \textit{urgenti}.  In
+Linux la distinzione ha senso solo per i dati urgenti dei socket (vedi
+sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce
+alle varie condizioni dei socket torneremo in sez.~\ref{sec:TCP_serv_poll},
+dove vedremo anche un esempio del suo utilizzo.
+
+Le costanti relative ai diversi tipi di dati normali e prioritari che fanno
+riferimento alle implementazioni in stile System V sono \const{POLLRDNORM},
+\const{POLLWRNORM}, \const{POLLRDBAND} e \const{POLLWRBAND}. Le prime due sono
+equivalenti rispettivamente a \const{POLLIN} e \const{POLLOUT},
+\const{POLLRDBAND} non viene praticamente mai usata su Linux mentre
+\const{POLLWRBAND} ha senso solo sui socket. In ogni caso queste costanti sono
+utilizzabili soltanto qualora si sia definita la macro
+\macro{\_XOPEN\_SOURCE}.
+
+In caso di successo \func{poll} ritorna restituendo il numero di file (un
+valore positivo) per i quali si è verificata una delle condizioni di attesa
+richieste o per i quali si è verificato un errore, avvalorando i relativi bit
+di \var{revents}. In caso di errori sui file vengono utilizzati i valori della
+terza sezione di tab.~\ref{tab:file_pollfd_flags} che hanno significato solo
+per \var{revents} (se specificati in \var{events} vengono ignorati). Un valore
+di ritorno nullo indica che si è raggiunto il timeout, mentre un valore
+negativo indica un errore nella chiamata, il cui codice viene riportato al
+solito tramite \var{errno}.
+
+L'uso di \func{poll} consente di superare alcuni dei problemi illustrati in
+precedenza per \func{select}; anzitutto, dato che in questo caso si usa un
+vettore di strutture \struct{pollfd} di dimensione arbitraria, non esiste il
+limite introdotto dalle dimensioni massime di un \textit{file descriptor set}
+e la dimensione dei dati passati al kernel dipende solo dal numero dei file
+descriptor che si vogliono controllare, non dal loro valore. Infatti, anche se
+usando dei bit un \textit{file descriptor set} può essere più efficiente di un
+vettore di strutture \struct{pollfd}, qualora si debba osservare un solo file
+descriptor con un valore molto alto ci si troverà ad utilizzare inutilmente un
+maggiore quantitativo di memoria.
+
+Inoltre con \func{select} lo stesso \textit{file descriptor set} è usato sia
+in ingresso che in uscita, e questo significa che tutte le volte che si vuole
+ripetere l'operazione occorre reinizializzarlo da capo. Questa operazione, che
+può essere molto onerosa se i file descriptor da tenere sotto osservazione
+sono molti, non è invece necessaria con \func{poll}.
+
+Abbiamo visto in sez.~\ref{sec:file_select} come lo standard POSIX preveda una
+variante di \func{select} che consente di gestire correttamente la ricezione
+dei segnali nell'attesa su un file descriptor.  Con l'introduzione di una
+implementazione reale di \func{pselect} nel kernel 2.6.16, è stata aggiunta
+anche una analoga funzione che svolga lo stesso ruolo per \func{poll}.
+
+In questo caso si tratta di una estensione che è specifica di Linux e non è
+prevista da nessuno standard; essa può essere utilizzata esclusivamente se si
+definisce la macro \macro{\_GNU\_SOURCE} ed ovviamente non deve essere usata
+se si ha a cuore la portabilità. La funzione è \funcd{ppoll}, ed il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/poll.h}
+\fdecl{int ppoll(struct pollfd *fds, nfds\_t nfds, 
+  const struct timespec *timeout, \\
+\phantom{int ppoll(}const sigset\_t *sigmask)} 
+
+\fdesc{Attende un cambiamento di stato su un insieme di file descriptor.}
+}
+
+{La funzione ritorna il numero di file descriptor con attività in caso di
+  successo, $0$ se c'è stato un timeout e $-1$ per un errore, nel qual caso
+  \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato in uno
+    degli insiemi.
+  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
+  \item[\errcode{EINVAL}] il valore di \param{nfds} eccede il limite
+    \const{RLIMIT\_NOFILE}.
+  \end{errlist}
+ed inoltre \errval{EFAULT} e \errval{ENOMEM} nel loro significato generico.
+}  
+\end{funcproto}
+
+La funzione ha lo stesso comportamento di \func{poll}, solo che si può
+specificare, con l'argomento \param{sigmask}, il puntatore ad una maschera di
+segnali; questa sarà la maschera utilizzata per tutto il tempo che la funzione
+resterà in attesa, all'uscita viene ripristinata la maschera originale.  L'uso
+di questa funzione è cioè equivalente, come illustrato nella pagina di
+manuale, all'esecuzione atomica del seguente codice:
+\includecodesnip{listati/ppoll_means.c} 
+
+Eccetto per \param{timeout}, che come per \func{pselect} deve essere un
+puntatore ad una struttura \struct{timespec}, gli altri argomenti comuni con
+\func{poll} hanno lo stesso significato, e la funzione restituisce gli stessi
+risultati illustrati in precedenza. Come nel caso di \func{pselect} la
+\textit{system call} che implementa \func{ppoll} restituisce, se la funzione
+viene interrotta da un segnale, il tempo mancante in \param{timeout}, e come
+per \func{pselect} la funzione di libreria fornita dalle \acr{glibc} maschera
+questo comportamento non modificando mai il valore di \param{timeout} anche se
+in questo caso non esiste nessuno standard che richieda questo comportamento.
+
+Infine anche per \func{poll} e \func{ppoll} valgono le considerazioni relative
+alla possibilità di avere delle notificazione spurie della disponibilità di
+accesso ai file descriptor illustrate per \func{select} in
+sez.~\ref{sec:file_select}, che non staremo a ripetere qui.
+
+\subsection{L'interfaccia di \textit{epoll}}
+\label{sec:file_epoll}
+
+\itindbeg{epoll}
+
+Nonostante \func{poll} presenti alcuni vantaggi rispetto a \func{select},
+anche questa funzione non è molto efficiente quando deve essere utilizzata con
+un gran numero di file descriptor,\footnote{in casi del genere \func{select}
+  viene scartata a priori, perché può avvenire che il numero di file
+  descriptor ecceda le dimensioni massime di un \textit{file descriptor set}.}
+in particolare nel caso in cui solo pochi di questi diventano attivi. Il
+problema in questo caso è che il tempo impiegato da \func{poll} a trasferire i
+dati da e verso il kernel è proporzionale al numero di file descriptor
+osservati, non a quelli che presentano attività.
+
+Quando ci sono decine di migliaia di file descriptor osservati e migliaia di
+eventi al secondo (il caso classico è quello di un server web di un sito con
+molti accessi) l'uso di \func{poll} comporta la necessità di trasferire avanti
+ed indietro da \textit{user space} a \textit{kernel space} una lunga lista di
+strutture \struct{pollfd} migliaia di volte al secondo. A questo poi si
+aggiunge il fatto che la maggior parte del tempo di esecuzione sarà impegnato
+ad eseguire una scansione su tutti i file descriptor tenuti sotto controllo
+per determinare quali di essi (in genere una piccola percentuale) sono
+diventati attivi. In una situazione come questa l'uso delle funzioni classiche
+dell'interfaccia dell'\textit{I/O multiplexing} viene a costituire un collo di
+bottiglia che degrada irrimediabilmente le prestazioni.
+
+Per risolvere questo tipo di situazioni sono state ideate delle interfacce
+specialistiche (come \texttt{/dev/poll} in Solaris, o \texttt{kqueue} in BSD)
+il cui scopo fondamentale è quello di restituire solamente le informazioni
+relative ai file descriptor osservati che presentano una attività, evitando
+così le problematiche appena illustrate. In genere queste prevedono che si
+registrino una sola volta i file descriptor da tenere sotto osservazione, e
+forniscono un meccanismo che notifica quali di questi presentano attività.
+
+Le modalità con cui avviene la notifica sono due, la prima è quella classica
+(quella usata da \func{poll} e \func{select}) che viene chiamata \textit{level
+  triggered}.\footnote{la nomenclatura è stata introdotta da Jonathan Lemon in
+  un articolo su \texttt{kqueue} al BSDCON 2000, e deriva da quella usata
+  nell'elettronica digitale.} In questa modalità vengono notificati i file
+descriptor che sono \textsl{pronti} per l'operazione richiesta, e questo
+avviene indipendentemente dalle operazioni che possono essere state fatte su
+di essi a partire dalla precedente notifica.  Per chiarire meglio il concetto
+ricorriamo ad un esempio: se su un file descriptor sono diventati disponibili
+in lettura 2000 byte ma dopo la notifica ne sono letti solo 1000 (ed è quindi
+possibile eseguire una ulteriore lettura dei restanti 1000), in modalità
+\textit{level triggered} questo sarà nuovamente notificato come
+\textsl{pronto}.
+
+La seconda modalità, è detta \textit{edge triggered}, e prevede che invece
+vengano notificati solo i file descriptor che hanno subito una transizione da
+\textsl{non pronti} a \textsl{pronti}. Questo significa che in modalità
+\textit{edge triggered} nel caso del precedente esempio il file descriptor
+diventato pronto da cui si sono letti solo 1000 byte non verrà nuovamente
+notificato come pronto, nonostante siano ancora disponibili in lettura 1000
+byte. Solo una volta che si saranno esauriti tutti i dati disponibili, e che
+il file descriptor sia tornato non essere pronto, si potrà ricevere una
+ulteriore notifica qualora ritornasse pronto.
+
+Nel caso di Linux al momento la sola interfaccia che fornisce questo tipo di
+servizio è chiamata \textit{epoll},\footnote{l'interfaccia è stata creata da
+  Davide Libenzi, ed è stata introdotta per la prima volta nel kernel 2.5.44,
+  ma la sua forma definitiva è stata raggiunta nel kernel 2.5.66, il supporto
+  è stato aggiunto nelle \acr{glibc} a partire dalla versione 2.3.2.} anche se
+sono state in discussione altre interfacce con le quali effettuare lo stesso
+tipo di operazioni; \textit{epoll} è in grado di operare sia in modalità
+\textit{level triggered} che \textit{edge triggered}.
+
+La prima versione di \textit{epoll} prevedeva l'apertura di uno speciale file
+di dispositivo, \texttt{/dev/epoll}, per ottenere un file descriptor da
+utilizzare con le funzioni dell'interfaccia ma poi si è passati all'uso di
+apposite \textit{system call}.  Il primo passo per usare l'interfaccia di
+\textit{epoll} è pertanto quello ottenere detto file descriptor chiamando una
+delle due funzioni di sistema \funcd{epoll\_create} e \funcd{epoll\_create1},
+i cui prototipi sono:
+
+\begin{funcproto}{
+\fhead{sys/epoll.h}
+\fdecl{int epoll\_create(int size)}
+\fdecl{int epoll\_create1(int flags)}
+
+\fdesc{Apre un file descriptor per \textit{epoll}.}
+}
+{Le funzioni ritornano un file descriptor per \textit{epoll} in caso di
+  successo e $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei
+  valori:
+  \begin{errlist}
+  \item[\errcode{EINVAL}] si è specificato un valore di \param{size} non
+    positivo o non valido per \param{flags}.
+  \item[\errcode{EMFILE}] si è raggiunto il limite sul numero massimo di
+    istanze di \textit{epoll} per utente stabilito da
+    \sysctlfiled{fs/epoll/max\_user\_instances}.
+  \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
+    nel sistema.
+  \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
+    l'istanza.
+  \end{errlist}
+}  
+\end{funcproto}
+
+Entrambe le funzioni restituiscono un file descriptor, detto anche
+\textit{epoll descriptor}; si tratta di un file descriptor speciale (per cui
+\func{read} e \func{write} non sono supportate) che viene associato alla
+infrastruttura utilizzata dal kernel per gestire la notifica degli eventi, e
+che può a sua volta essere messo sotto osservazione con una chiamata a
+\func{select}, \func{poll} o \func{epoll\_ctl}; in tal caso risulterà pronto
+quando saranno disponibili eventi da notificare riguardo i file descriptor da
+lui osservati.\footnote{è anche possibile inviarlo ad un altro processo
+  attraverso un socket locale (vedi sez.~\ref{sec:sock_fd_passing}) ma
+  l'operazione non ha alcun senso dato che il nuovo processo non avrà a
+  disposizione le copie dei file descriptor messe sotto osservazione tramite
+  esso.} Una volta che se ne sia terminato l'uso si potranno rilasciare tutte
+le risorse allocate chiudendolo semplicemente con \func{close}.
+
+Nel caso di \func{epoll\_create} l'argomento \param{size} serviva a dare
+l'indicazione del numero di file descriptor che si vorranno tenere sotto
+controllo, e costituiva solo un suggerimento per semplificare l'allocazione di
+risorse sufficienti, non un valore massimo, ma a partire dal kernel 2.6.8 esso
+viene totalmente ignorato e l'allocazione è sempre dinamica.
+
+La seconda versione della funzione, \func{epoll\_create1} è stata introdotta
+come estensione della precedente (è disponibile solo a partire dal kernel
+2.6.27) per poter passare dei flag di controllo come maschera binaria in fase
+di creazione del file descriptor. Al momento l'unico valore legale
+per \param{flags} (a parte lo zero) è \constd{EPOLL\_CLOEXEC}, che consente di
+impostare in maniera atomica sul file descriptor il flag di
+\textit{close-on-exec} (si è trattato il significato di \const{O\_CLOEXEC} in
+sez.~\ref{sec:file_open_close}), senza che sia necessaria una successiva
+chiamata a \func{fcntl}.
+
+Una volta ottenuto un file descriptor per \textit{epoll} il passo successivo è
+indicare quali file descriptor mettere sotto osservazione e quali operazioni
+controllare, per questo si deve usare la seconda funzione di sistema
+dell'interfaccia, \funcd{epoll\_ctl}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/epoll.h}
+\fdecl{int epoll\_ctl(int epfd, int op, int fd, struct epoll\_event *event)}
+
+\fdesc{Esegue le operazioni di controllo di \textit{epoll}.}
+}
+
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] i file descriptor \param{epfd} o \param{fd} non sono
+    validi.
+  \item[\errcode{EEXIST}] l'operazione richiesta è \const{EPOLL\_CTL\_ADD} ma
+    \param{fd} è già stato inserito in \param{epfd}.
+  \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+    con \func{epoll\_create}, o \param{fd} è lo stesso \param{epfd} o
+    l'operazione richiesta con \param{op} non è supportata.
+  \item[\errcode{ENOENT}] l'operazione richiesta è \const{EPOLL\_CTL\_MOD} o
+    \const{EPOLL\_CTL\_DEL} ma \param{fd} non è inserito in \param{epfd}.
+  \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel gestire
+    l'operazione richiesta.
+  \item[\errcode{ENOSPC}] si è raggiunto il limite massimo di registrazioni
+    per utente di file descriptor da osservare imposto da
+    \sysctlfiled{fs/epoll/max\_user\_watches}.
+  \item[\errcode{EPERM}] il file associato a \param{fd} non supporta l'uso di
+    \textit{epoll}.
+  \end{errlist}
+  }  
+\end{funcproto}
+
+La funzione prende sempre come primo argomento un file descriptor di
+\textit{epoll}, \param{epfd}, che indica quale istanza di \textit{epoll} usare
+e deve pertanto essere stato ottenuto in precedenza con una chiamata a
+\func{epoll\_create} o \func{epoll\_create1}. L'argomento \param{fd} indica
+invece il file descriptor che si vuole tenere sotto controllo, quest'ultimo
+può essere un qualunque file descriptor utilizzabile con \func{poll}, ed anche
+un altro file descriptor di \textit{epoll}, ma non lo stesso \param{epfd}.
+
+Il comportamento della funzione viene controllato dal valore dall'argomento
+\param{op} che consente di specificare quale operazione deve essere eseguita.
+Le costanti che definiscono i valori utilizzabili per \param{op}
+sono riportate in tab.~\ref{tab:epoll_ctl_operation}, assieme al significato
+delle operazioni cui fanno riferimento.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{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.\\
+    \constd{EPOLL\_CTL\_MOD}& Modifica le modalità di osservazione del file
+                              descriptor \param{fd} secondo il contenuto di
+                              \param{event}.\\
+    \constd{EPOLL\_CTL\_DEL}& Rimuove il file descriptor \param{fd} dalla lista
+                              dei file controllati tramite \param{epfd}.\\
+   \hline    
+  \end{tabular}
+  \caption{Valori dell'argomento \param{op} che consentono di scegliere quale
+    operazione di controllo effettuare con la funzione \func{epoll\_ctl}.} 
+  \label{tab:epoll_ctl_operation}
+\end{table}
+
+% era stata aggiunta EPOLL_CTL_DISABLE in previsione del kernel 3.7, vedi
+% http://lwn.net/Articles/520012/ e http://lwn.net/Articles/520198/
+% ma non è mai stata inserita.
+
+Le modalità di utilizzo di \textit{epoll} prevedono che si definisca qual'è
+l'insieme dei file descriptor da tenere sotto controllo utilizzando una serie
+di chiamate a \const{EPOLL\_CTL\_ADD}.\footnote{un difetto dell'interfaccia è
+  che queste chiamate devono essere ripetute per ciascun file descriptor,
+  incorrendo in una perdita di prestazioni qualora il numero di file
+  descriptor sia molto grande; per questo è stato proposto di introdurre come
+  estensione una funzione \code{epoll\_ctlv} che consenta di effettuare con
+  una sola chiamata le impostazioni per un blocco di file descriptor.} L'uso
+di \const{EPOLL\_CTL\_MOD} consente in seguito di modificare le modalità di
+osservazione di un file descriptor che sia già stato aggiunto alla lista di
+osservazione. Qualora non si abbia più interesse nell'osservazione di un file
+descriptor lo si può rimuovere dalla lista associata a \param{epfd} con
+\const{EPOLL\_CTL\_DEL}.
+
+Anche se è possibile tenere sotto controllo lo stesso file descriptor in due
+istanze distinte di \textit{epoll} in genere questo è sconsigliato in quanto
+entrambe riceveranno le notifiche, e gestire correttamente le notifiche
+multiple richiede molta attenzione. Se invece si cerca di inserire due volte
+lo stesso file descriptor nella stessa istanza di \textit{epoll} la funzione
+fallirà con un errore di \errval{EEXIST}.  Tuttavia è possibile inserire nella
+stessa istanza file descriptor duplicati (si ricordi quanto visto in
+sez.~\ref{sec:file_dup}), una tecnica che può essere usata per registrarli con
+un valore diverso per \param{events} e classificare così diversi tipi di
+eventi.
+
+Si tenga presente che quando si chiude un file descriptor questo, se era stato
+posto sotto osservazione da una istanza di \textit{epoll}, viene rimosso
+automaticamente solo nel caso esso sia l'unico riferimento al file aperto
+sottostante (più precisamente alla struttura \kstruct{file}, si ricordi
+fig.~\ref{fig:file_dup}) e non è necessario usare
+\const{EPOLL\_CTL\_DEL}. Questo non avviene qualora esso sia stato duplicato
+(perché la suddetta struttura non viene disallocata) e si potranno ricevere
+eventi ad esso relativi anche dopo che lo si è chiuso; per evitare
+l'inconveniente è necessario rimuoverlo esplicitamente con
+\const{EPOLL\_CTL\_DEL}.
+
+L'ultimo argomento, \param{event}, deve essere un puntatore ad una struttura
+di tipo \struct{epoll\_event}, ed ha significato solo con le operazioni
+\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD}, per le quali serve ad
+indicare quale tipo di evento relativo ad \param{fd} si vuole che sia tenuto
+sotto controllo.  L'argomento viene ignorato con l'operazione
+\const{EPOLL\_CTL\_DEL}.\footnote{fino al kernel 2.6.9 era comunque richiesto
+  che questo fosse un puntatore valido, anche se poi veniva ignorato; a
+  partire dal 2.6.9 si può specificare anche un valore \val{NULL} ma se si
+  vuole mantenere la compatibilità con le versioni precedenti occorre usare un
+  puntatore valido.}
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{0.90\textwidth}
+    \includestruct{listati/epoll_event.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{epoll\_event}, che consente di specificare
+    gli eventi associati ad un file descriptor controllato con
+    \textit{epoll}.}
+  \label{fig:epoll_event}
+\end{figure}
+
+La struttura \struct{epoll\_event} è l'analoga di \struct{pollfd} e come
+quest'ultima serve sia in ingresso (quando usata con \func{epoll\_ctl}) ad
+impostare quali eventi osservare, che in uscita (nei risultati ottenuti con
+\func{epoll\_wait}) per ricevere le notifiche degli eventi avvenuti.  La sua
+definizione è riportata in fig.~\ref{fig:epoll_event}. 
+
+Il primo campo, \var{events}, è una maschera binaria in cui ciascun bit
+corrisponde o ad un tipo di evento, o una modalità di notifica; detto campo
+deve essere specificato come OR aritmetico delle costanti riportate in
+tab.~\ref{tab:epoll_events}. Nella prima parte della tabella si sono indicate
+le costanti che permettono di indicare il tipo di evento, che sono le
+equivalenti delle analoghe di tab.~\ref{tab:file_pollfd_flags} per
+\func{poll}. Queste sono anche quelle riportate nella struttura
+\struct{epoll\_event} restituita da \func{epoll\_wait} per indicare il tipo di
+evento presentatosi, insieme a quelle della seconda parte della tabella, che
+vengono comunque riportate anche se non le si sono impostate con
+\func{epoll\_ctl}. La terza parte della tabella contiene le costanti che
+modificano le modalità di notifica.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{EPOLLIN}     & Il file è pronto per le operazioni di lettura
+                          (analogo di \const{POLLIN}).\\
+    \constd{EPOLLOUT}    & Il file è pronto per le operazioni di scrittura
+                          (analogo di \const{POLLOUT}).\\
+    \constd{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\\
+    \constd{EPOLLPRI}    & Ci sono dati urgenti disponibili in lettura (analogo
+                          di \const{POLLPRI}); questa condizione viene comunque
+                          riportata in uscita, e non è necessaria impostarla
+                          in ingresso.\\ 
+    \hline
+    \constd{EPOLLERR}    & Si è verificata una condizione di errore 
+                          (analogo di \const{POLLERR}); questa condizione
+                          viene comunque riportata in uscita, e non è
+                          necessaria impostarla in ingresso.\\
+    \constd{EPOLLHUP}    & Si è verificata una condizione di hung-up; questa
+                          condizione viene comunque riportata in uscita, e non
+                          è necessaria impostarla in ingresso.\\
+    \hline
+    \constd{EPOLLET}     & Imposta la notifica in modalità \textit{edge
+                            triggered} per il file descriptor associato.\\ 
+    \constd{EPOLLONESHOT}& Imposta la modalità \textit{one-shot} per il file
+                          descriptor associato (questa modalità è disponibile
+                          solo a partire dal kernel 2.6.2).\\
+    \constd{EPOLLWAKEUP} & Attiva la prevenzione della sospensione del sistema
+                          se il file descriptor che si è marcato con esso
+                          diventa pronto (aggiunto a partire dal kernel 3.5),
+                          può essere impostato solo dall'amministratore (o da
+                          un processo con la capacità
+                          \const{CAP\_BLOCK\_SUSPEND}).\\ 
+    \hline
+  \end{tabular}
+  \caption{Costanti che identificano i bit del campo \param{events} di
+    \struct{epoll\_event}.}
+  \label{tab:epoll_events}
+\end{table}
+
+\footnotetext{questa modalità è disponibile solo a partire dal kernel 2.6.17,
+  ed è utile per riconoscere la chiusura di una connessione dall'altro capo di
+  un socket quando si lavora in modalità \textit{edge triggered}.}
+
+% TODO aggiunto con il kernel 4.5  EPOLLEXCLUSIVE, vedi
+% http://lwn.net/Articles/633422/#excl 
+
+Il secondo campo, \var{data}, è una \dirct{union} che serve a identificare il
+file descriptor a cui si intende fare riferimento, ed in astratto può
+contenere un valore qualsiasi (specificabile in diverse forme) che ne permetta
+una indicazione univoca. Il modo più comune di usarlo però è quello in cui si
+specifica il terzo argomento di \func{epoll\_ctl} nella forma
+\var{event.data.fd}, assegnando come valore di questo campo lo stesso valore
+dell'argomento \param{fd}, cosa che permette una immediata identificazione del
+file descriptor.
+
+% TODO verificare se prima o poi epoll_ctlv verrà introdotta
+
+Le impostazioni di default prevedono che la notifica degli eventi richiesti
+sia effettuata in modalità \textit{level triggered}, a meno che sul file
+descriptor non si sia impostata la modalità \textit{edge triggered},
+registrandolo con \const{EPOLLET} attivo nel campo \var{events}.  
+
+Infine una particolare modalità di notifica è quella impostata con
+\const{EPOLLONESHOT}: a causa dell'implementazione di \textit{epoll} infatti
+quando si è in modalità \textit{edge triggered} l'arrivo in rapida successione
+di dati in blocchi separati (questo è tipico con i socket di rete, in quanto i
+dati arrivano a pacchetti) può causare una generazione di eventi (ad esempio
+segnalazioni di dati in lettura disponibili) anche se la condizione è già
+stata rilevata (si avrebbe cioè una rottura della logica \textit{edge
+  triggered}).
+
+Anche se la situazione è facile da gestire, la si può evitare utilizzando
+\const{EPOLLONESHOT} per impostare la modalità \textit{one-shot}, in cui la
+notifica di un evento viene effettuata una sola volta, dopo di che il file
+descriptor osservato, pur restando nella lista di osservazione, viene
+automaticamente disattivato (la cosa avviene contestualmente al ritorno di
+\func{epoll\_wait} a causa dell'evento in questione) e per essere riutilizzato
+dovrà essere riabilitato esplicitamente con una successiva chiamata con
+\const{EPOLL\_CTL\_MOD}.
+
+Una volta impostato l'insieme di file descriptor che si vogliono osservare con
+i relativi eventi, la funzione di sistema che consente di attendere
+l'occorrenza di uno di tali eventi è \funcd{epoll\_wait}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/epoll.h}
+\fdecl{int epoll\_wait(int epfd, struct epoll\_event * events, int maxevents,
+  int timeout)}
+
+\fdesc{Attende che uno dei file descriptor osservati sia pronto.}
+}
+
+{La funzione ritorna il numero di file descriptor pronti in caso di successo e
+  $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] il file descriptor \param{epfd} non è valido.
+  \item[\errcode{EFAULT}] il puntatore \param{events} non è valido.
+  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
+    della scadenza di \param{timeout}.
+  \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+    con \func{epoll\_create}, o \param{maxevents} non è maggiore di zero.
+  \end{errlist}
+}  
+\end{funcproto}
+
+La funzione si blocca in attesa di un evento per i file descriptor registrati
+nella lista di osservazione di \param{epfd} fino ad un tempo massimo
+specificato in millisecondi tramite l'argomento \param{timeout}. Gli eventi
+registrati vengono riportati in un vettore di strutture \struct{epoll\_event}
+(che deve essere stato allocato in precedenza) all'indirizzo indicato
+dall'argomento \param{events}, fino ad un numero massimo di eventi impostato
+con l'argomento \param{maxevents}.
+
+La funzione ritorna il numero di eventi rilevati, o un valore nullo qualora
+sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo,
+oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che
+indica di non attendere e ritornare immediatamente (anche in questo caso il
+valore di ritorno sarà nullo) o il valore $-1$, che indica un'attesa
+indefinita. L'argomento \param{maxevents} dovrà invece essere sempre un intero
+positivo.
+
+Come accennato la funzione restituisce i suoi risultati nel vettore di
+strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel
+campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli
+eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era
+stato impostato per il file descriptor per cui si è verificato l'evento quando
+questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
+\const{EPOLL\_CTL\_ADD}, in questo modo il campo \var{data} consente di
+identificare il file descriptor, ed è per questo che, come accennato, è
+consuetudine usare per \var{data} il valore del file descriptor stesso.
+
+Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da
+come si è impostata la modalità di osservazione (se \textit{level triggered} o
+\textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura
+che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait}
+questi vengano combinati. Inoltre qualora su un file descriptor fossero
+presenti eventi non ancora notificati, e si effettuasse una modifica
+dell'osservazione con \const{EPOLL\_CTL\_MOD}, questi verrebbero riletti alla
+luce delle modifiche.
+
+Si tenga presente infine che con l'uso della modalità \textit{edge triggered}
+il ritorno di \func{epoll\_wait} avviene solo quando il file descriptor ha
+cambiato stato diventando pronto. Esso non sarà riportato nuovamente fino ad
+un altro cambiamento di stato, per cui occorre assicurarsi di aver
+completamente esaurito le operazioni su di esso.  Questa condizione viene
+generalmente rilevata dall'occorrere di un errore di \errcode{EAGAIN} al
+ritorno di una \func{read} o una \func{write}, (è opportuno ricordare ancora
+una volta che l'uso dell'\textit{I/O multiplexing} richiede di operare sui
+file in modalità non bloccante) ma questa non è la sola modalità possibile, ad
+esempio la condizione può essere riconosciuta anche per il fatto che sono
+stati restituiti meno dati di quelli richiesti.
+
+Si tenga presente che in modalità \textit{edge triggered}, dovendo esaurire le
+attività di I/O dei file descriptor risultati pronti per poter essere
+rinotificati, la gestione elementare per cui li si trattano uno per uno in
+sequenza può portare ad un effetto denominato \textit{starvation}
+(``\textsl{carestia}'').  Si rischia cioè di concentrare le operazioni sul
+primo file descriptor che dispone di molti dati, prolungandole per tempi molto
+lunghi con un ritardo che può risultare eccessivo nei confronti di quelle da
+eseguire sugli altri che verrebbero dopo.  Per evitare questo tipo di
+problematiche viene consigliato di usare \func{epoll\_wait} per registrare un
+elenco dei file descriptor da gestire, e di trattarli a turno in maniera più
+equa.
+
+Come già per \func{select} e \func{poll} anche per l'interfaccia di
+\textit{epoll} si pone il problema di gestire l'attesa di segnali e di dati
+contemporaneamente.  Valgono le osservazioni fatte in
+sez.~\ref{sec:file_select}, e per poterlo fare di nuovo è necessaria una
+variante della funzione di attesa che consenta di reimpostare all'uscita una
+maschera di segnali, analoga alle estensioni \func{pselect} e \func{ppoll} che
+abbiamo visto in precedenza per \func{select} e \func{poll}. In questo caso la
+funzione di sistema si chiama \funcd{epoll\_pwait}\footnote{la funzione è
+  stata introdotta a partire dal kernel 2.6.19, ed è, come tutta l'interfaccia
+  di \textit{epoll}, specifica di Linux.} ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/epoll.h}
+\fdecl{int epoll\_pwait(int epfd, struct epoll\_event * events, int maxevents, 
+    int timeout, \\
+\phantom{int epoll\_pwait(}const sigset\_t *sigmask)}
+
+\fdesc{Attende che uno dei file descriptor osservati sia pronto, mascherando
+    i segnali.}  }
+
+{La funzione ritorna il numero di file descriptor pronti in caso di successo e
+  $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori già
+  visti con \func{epoll\_wait}.
+
+}  
+\end{funcproto}
+
+La funzione è del tutto analoga \func{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 \textit{race
+  condition} sono state introdotte estensioni dello standard POSIX e funzioni
+apposite come \func{pselect}, \func{ppoll} e \func{epoll\_pwait}.
+
+Benché i segnali siano il meccanismo più usato per effettuare notifiche ai
+processi, la loro interfaccia di programmazione, che comporta l'esecuzione di
+una funzione di gestione in maniera asincrona e totalmente scorrelata
+dall'ordinario flusso di esecuzione del processo, si è però dimostrata quasi
+subito assai problematica. Oltre ai limiti relativi ai limiti al cosa si può
+fare all'interno della funzione del gestore di segnali (quelli illustrati in
+sez.~\ref{sec:sig_signal_handler}), c'è il problema più generale consistente
+nel fatto che questa modalità di funzionamento cozza con altre interfacce di
+programmazione previste dal sistema in cui si opera in maniera
+\textsl{sincrona}, come quelle dell'\textit{I/O multiplexing} appena
+illustrate.
+
+In questo tipo di interfacce infatti ci si aspetta che il processo gestisca
+gli eventi a cui deve reagire in maniera sincrona generando le opportune
+risposte, mentre con l'arrivo di un segnale si possono avere interruzioni
+asincrone in qualunque momento.  Questo comporta la necessità di dover
+gestire, quando si deve tener conto di entrambi i tipi di eventi, le
+interruzioni delle funzioni di attesa sincrone, ed evitare possibili
+\textit{race conditions}. In sostanza se non ci fossero i segnali non ci
+sarebbe da preoccuparsi, fintanto che si effettuano operazioni all'interno di
+un processo, della non atomicità delle \textit{system call} lente che vengono
+interrotte e devono essere riavviate.
+
+Abbiamo visto però in sez.~\ref{sec:sig_real_time} che insieme ai segnali
+\textit{real-time} sono state introdotte anche delle interfacce di gestione
+sincrona dei segnali, con la funzione \func{sigwait} e le sue affini. Queste
+funzioni consentono di gestire i segnali bloccando un processo fino alla
+avvenuta ricezione e disabilitando l'esecuzione asincrona rispetto al resto
+del programma del gestore del segnale. Questo consente di risolvere i problemi
+di atomicità nella gestione degli eventi associati ai segnali, avendo tutto il
+controllo nel flusso principale del programma, ottenendo così una gestione
+simile a quella dell'\textit{I/O multiplexing}, ma non risolve i problemi
+delle interazioni con quest'ultimo, perché o si aspetta la ricezione di un
+segnale o si aspetta che un file descriptor sia accessibile e nessuna delle
+rispettive funzioni consente di fare contemporaneamente entrambe le cose.
+
+Per risolvere questo problema nello sviluppo del kernel si è pensato di
+introdurre un meccanismo alternativo per la notifica dei segnali (esteso anche
+ad altri eventi generici) che, ispirandosi di nuovo alla filosofia di Unix per
+cui tutto è un file, consentisse di eseguire la notifica con l'uso di
+opportuni file descriptor. Ovviamente si tratta di una funzionalità specifica
+di Linux, non presente in altri sistemi unix-like, e non prevista da nessuno
+standard, per cui va evitata se si ha a cuore la portabilità.
+
+In sostanza, come per \func{sigwait}, si può disabilitare l'esecuzione di un
+gestore in occasione dell'arrivo di un segnale, e rilevarne l'avvenuta
+ricezione leggendone la notifica tramite l'uso di uno speciale file
+descriptor. Trattandosi di un file descriptor questo potrà essere tenuto sotto
+osservazione con le ordinarie funzioni dell'\textit{I/O multiplexing} (vale a
+dire con le solite \func{select}, \func{poll} e \func{epoll\_wait}) allo
+stesso modo di quelli associati a file o socket, per cui alla fine si potrà
+attendere in contemporanea sia l'arrivo del segnale che la disponibilità di
+accesso ai dati relativi a questi ultimi.
+
+La funzione di sistema che permette di abilitare la ricezione dei segnali
+tramite file descriptor è \funcd{signalfd},\footnote{in realtà quella
+  riportata è l'interfaccia alla funzione fornita dalle \acr{glibc}, esistono
+  infatti due versioni diverse della \textit{system call}; una prima versione,
+  \func{signalfd}, introdotta nel kernel 2.6.22 e disponibile con le
+  \acr{glibc} 2.8 che non supporta l'argomento \texttt{flags}, ed una seconda
+  versione, \funcm{signalfd4}, introdotta con il kernel 2.6.27 e che è quella
+  che viene sempre usata a partire dalle \acr{glibc} 2.9, che prende un
+  argomento aggiuntivo \code{size\_t sizemask} che indica la dimensione della
+  maschera dei segnali, il cui valore viene impostato automaticamente dalle
+  \acr{glibc}.}  il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/signalfd.h}
+\fdecl{int signalfd(int fd, const sigset\_t *mask, int flags)}
+
+\fdesc{Crea o modifica un file descriptor per la ricezione dei segnali.}
+}
+
+{La funzione ritorna un numero di file descriptor in caso di successo e $-1$
+  per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] il valore \param{fd} non indica un file descriptor.
+  \item[\errcode{EINVAL}] il file descriptor \param{fd} non è stato ottenuto
+    con \func{signalfd} o il valore di \param{flags} non è valido.
+  \item[\errcode{ENODEV}] il kernel non può montare internamente il
+    dispositivo per la gestione anonima degli \textit{inode}
+    associati al file descriptor.
+  \item[\errcode{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file
+    descriptor di \func{signalfd}.
+  \end{errlist}
+  ed inoltre \errval{EMFILE} e \errval{ENFILE} nel loro significato generico.
+  
+}  
+\end{funcproto}
+
+La funzione consente di creare o modificare le caratteristiche di un file
+descriptor speciale su cui ricevere le notifiche della ricezione di
+segnali. Per creare ex-novo uno di questi file descriptor è necessario passare
+$-1$ come valore per l'argomento \param{fd}, ogni altro valore positivo verrà
+invece interpretato come il numero del file descriptor (che deve esser stato
+precedentemente creato sempre con \func{signalfd}) di cui si vogliono
+modificare le caratteristiche. Nel primo caso la funzione ritornerà il valore
+del nuovo file descriptor e nel secondo caso il valore indicato
+con \param{fd}, in caso di errore invece verrà restituito $-1$.
+
+L'elenco dei segnali che si vogliono gestire con \func{signalfd} deve essere
+specificato tramite l'argomento \param{mask}. Questo deve essere passato come
+puntatore ad una maschera di segnali creata con l'uso delle apposite macro già
+illustrate in sez.~\ref{sec:sig_sigset}. La maschera deve indicare su quali
+segnali si intende operare con \func{signalfd}; l'elenco può essere modificato
+con una successiva chiamata a \func{signalfd}. Dato che \signal{SIGKILL} e
+\signal{SIGSTOP} non possono essere intercettati (e non prevedono neanche la
+possibilità di un gestore) un loro inserimento nella maschera verrà ignorato
+senza generare errori.
+
+L'argomento \param{flags} consente di impostare direttamente in fase di
+creazione due flag per il file descriptor analoghi a quelli che si possono
+impostare con una creazione ordinaria con \func{open}, evitando una
+impostazione successiva con \func{fcntl} (si ricordi che questo è un argomento
+aggiuntivo, introdotto con la versione fornita a partire dal kernel 2.6.27,
+per kernel precedenti il valore deve essere nullo).  L'argomento deve essere
+specificato come maschera binaria dei valori riportati in
+tab.~\ref{tab:signalfd_flags}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{SFD\_NONBLOCK}&imposta sul file descriptor il flag di
+                           \const{O\_NONBLOCK} per renderlo non bloccante.\\ 
+    \constd{SFD\_CLOEXEC}& imposta il flag di \const{O\_CLOEXEC} per la
+                           chiusura automatica del file descriptor nella
+                           esecuzione di \func{exec}.\\
+    \hline    
+  \end{tabular}
+  \caption{Valori dell'argomento \param{flags} per la funzione \func{signalfd}
+    che consentono di impostare i flag del file descriptor.} 
+  \label{tab:signalfd_flags}
+\end{table}
+
+Si tenga presente che la chiamata a \func{signalfd} non disabilita la gestione
+ordinaria dei segnali indicati da \param{mask}; questa, se si vuole effettuare
+la ricezione tramite il file descriptor, dovrà essere disabilitata
+esplicitamente bloccando gli stessi segnali con \func{sigprocmask}, altrimenti
+verranno comunque eseguite le azioni di default (o un eventuale gestore
+installato in precedenza). Il blocco non ha invece nessun effetto sul file
+descriptor restituito da \func{signalfd}, dal quale sarà possibile pertanto
+ricevere qualunque segnale, anche se questo risultasse bloccato.
+
+Si tenga presente inoltre che la lettura di una struttura
+\struct{signalfd\_siginfo} relativa ad un segnale pendente è equivalente alla
+esecuzione di un gestore, vale a dire che una volta letta il segnale non sarà
+più pendente e non potrà essere ricevuto, qualora si ripristino le normali
+condizioni di gestione, né da un gestore, né dalla funzione \func{sigwaitinfo}.
+
+Come anticipato, essendo questo lo scopo principale della nuova interfaccia,
+il file descriptor può essere tenuto sotto osservazione tramite le funzioni
+dell'\textit{I/O multiplexing} (vale a dire con le solite \func{select},
+\func{poll} e \func{epoll\_wait}), e risulterà accessibile in lettura quando
+uno o più dei segnali indicati tramite \param{mask} sarà pendente.
+
+La funzione può essere chiamata più volte dallo stesso processo, consentendo
+così di tenere sotto osservazione segnali diversi tramite file descriptor
+diversi. Inoltre è anche possibile tenere sotto osservazione lo stesso segnale
+con più file descriptor, anche se la pratica è sconsigliata; in tal caso la
+ricezione del segnale potrà essere effettuata con una lettura da uno qualunque
+dei file descriptor a cui è associato, ma questa potrà essere eseguita
+soltanto una volta. Questo significa che tutti i file descriptor su cui è
+presente lo stesso segnale risulteranno pronti in lettura per le funzioni di
+\textit{I/O multiplexing}, ma una volta eseguita la lettura su uno di essi il
+segnale sarà considerato ricevuto ed i relativi dati non saranno più
+disponibili sugli altri file descriptor, che (a meno di una ulteriore
+occorrenza del segnale nel frattempo) di non saranno più pronti.
+
+Quando il file descriptor per la ricezione dei segnali non serve più potrà
+essere chiuso con \func{close} liberando tutte le risorse da esso allocate. In
+tal caso qualora vi fossero segnali pendenti questi resteranno tali, e
+potranno essere ricevuti normalmente una volta che si rimuova il blocco
+imposto con \func{sigprocmask}.
+
+Oltre che con le funzioni dell'\textit{I/O multiplexing} l'uso del file
+descriptor restituito da \func{signalfd} cerca di seguire la semantica di un
+sistema unix-like anche con altre \textit{system call}; in particolare esso
+resta aperto (come ogni altro file descriptor) attraverso una chiamata ad
+\func{exec}, a meno che non lo si sia creato con il flag di
+\const{SFD\_CLOEXEC} o si sia successivamente impostato il
+\textit{close-on-exec} con \func{fcntl}. Questo comportamento corrisponde
+anche alla ordinaria semantica relativa ai segnali bloccati, che restano
+pendenti attraverso una \func{exec}.
+
+Analogamente il file descriptor resta sempre disponibile attraverso una
+\func{fork} per il processo figlio, che ne riceve una copia; in tal caso però
+il figlio potrà leggere dallo stesso soltanto i dati relativi ai segnali
+ricevuti da lui stesso. Nel caso di \textit{thread} viene nuovamente seguita
+la semantica ordinaria dei segnali, che prevede che un singolo \textit{thread}
+possa ricevere dal file descriptor solo le notifiche di segnali inviati
+direttamente a lui o al processo in generale, e non quelli relativi ad altri
+\textit{thread} appartenenti allo stesso processo.
+
+L'interfaccia fornita da \func{signalfd} prevede che la ricezione dei segnali
+sia eseguita leggendo i dati relativi ai segnali pendenti dal file descriptor
+restituito dalla funzione con una normalissima \func{read}.  Qualora non vi
+siano segnali pendenti la \func{read} si bloccherà a meno di non aver
+impostato la modalità di I/O non bloccante sul file descriptor, o direttamente
+in fase di creazione con il flag \const{SFD\_NONBLOCK}, o in un momento
+successivo con \func{fcntl}.  
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{0.90\textwidth}
+    \includestruct{listati/signalfd_siginfo.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{signalfd\_siginfo}, restituita in lettura da
+    un file descriptor creato con \func{signalfd}.}
+  \label{fig:signalfd_siginfo}
+\end{figure}
+
+I dati letti dal file descriptor vengono scritti sul buffer indicato come
+secondo argomento di \func{read} nella forma di una sequenza di una o più
+strutture \struct{signalfd\_siginfo} (la cui definizione si è riportata in
+fig.~\ref{fig:signalfd_siginfo}) a seconda sia della dimensione del buffer che
+del numero di segnali pendenti. Per questo motivo il buffer deve essere almeno
+di dimensione pari a quella di \struct{signalfd\_siginfo}, qualora sia di
+dimensione maggiore potranno essere letti in unica soluzione i dati relativi
+ad eventuali più segnali pendenti, fino al numero massimo di strutture
+\struct{signalfd\_siginfo} che possono rientrare nel buffer.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{\codesamplewidth}
+    \includecodesample{listati/FifoReporter-init.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Sezione di inizializzazione del codice del programma
+    \file{FifoReporter.c}.}
+  \label{fig:fiforeporter_code_init}
+\end{figure}
+
+Il contenuto di \struct{signalfd\_siginfo} ricalca da vicino quella della
+analoga struttura \struct{siginfo\_t} (illustrata in
+fig.~\ref{fig:sig_siginfo_t}) usata dall'interfaccia ordinaria dei segnali, e
+restituisce dati simili. Come per \struct{siginfo\_t} i campi che vengono
+avvalorati dipendono dal tipo di segnale e ricalcano i valori che abbiamo già
+illustrato in sez.~\ref{sec:sig_sigaction}.\footnote{si tenga presente però
+  che per un bug i kernel fino al 2.6.25 non avvalorano correttamente i campi
+  \var{ssi\_ptr} e \var{ssi\_int} per segnali inviati con \func{sigqueue}.}
+
+Come esempio di questa nuova interfaccia ed anche come esempio di applicazione
+della interfaccia di \textit{epoll}, si è scritto un programma elementare che
+stampi sullo \textit{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 \textit{epoll} e \func{signalfd}, a partire (\texttt{\small 12-16})
+dalla definizione delle varie variabili e strutture necessarie. Al solito si è
+tralasciata la parte dedicata alla decodifica delle opzioni che consentono ad
+esempio di cambiare il nome del file associato alla \textit{fifo}.
+
+Il primo passo (\texttt{\small 19-20}) è la creazione di un file descriptor
+\texttt{epfd} di \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 \textit{epoll} in maniera del tutto
+analoga a quanto fatto con quello relativo alla notifica dei segnali.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{\codesamplewidth}
+    \includecodesample{listati/FifoReporter-main.c}
+  \end{minipage} 
+  \normalsize 
+  \caption{Ciclo principale del codice del programma \file{FifoReporter.c}.}
+  \label{fig:fiforeporter_code_body}
+\end{figure}
+
+Una volta completata l'inizializzazione verrà eseguito indefinitamente il
+ciclo principale del programma (\texttt{\small 2-45}) che si è riportato in
+fig.~\ref{fig:fiforeporter_code_body}, fintanto che questo non riceva un
+segnale di \signal{SIGINT} (ad esempio con la pressione di \texttt{C-c}). Il
+ciclo prevede che si attenda (\texttt{\small 2-3}) la presenza di un file
+descriptor pronto in lettura con \func{epoll\_wait} (si ricordi che entrambi i
+file descriptor \var{fifofd} e \var{sigfd} sono stati posti in osservazioni
+per eventi di tipo \const{EPOLLIN}) che si bloccherà fintanto che non siano
+stati scritti dati sulla \textit{fifo} o che non sia arrivato un
+segnale.\footnote{per semplificare il codice non si è trattato il caso in cui
+  \func{epoll\_wait} viene interrotta da un segnale, assumendo che tutti
+  quelli che possano interessare siano stati predisposti per la notifica
+  tramite file descriptor, per gli altri si otterrà semplicemente l'uscita dal
+  programma.}
+
+Anche se in questo caso i file descriptor pronti possono essere al più due, si
+è comunque adottato un approccio generico in cui questi verranno letti
+all'interno di un opportuno ciclo (\texttt{\small 5-44}) sul numero
+restituito da \func{epoll\_wait}, esaminando i risultati presenti nel vettore
+\var{events} all'interno di una catena di condizionali alternativi sul valore
+del file descriptor riconosciuto come pronto, controllando cioè a quale dei
+due file descriptor possibili corrisponde il campo relativo,
+\var{events[i].data.fd}.
+
+Il primo condizionale (\texttt{\small 6-24}) è relativo al caso che si sia
+ricevuto un segnale e che il file descriptor pronto corrisponda
+(\texttt{\small 6}) a \var{sigfd}. Dato che in generale si possono ricevere
+anche notifiche relativi a più di un singolo segnale, si è scelto di leggere
+una struttura \struct{signalfd\_siginfo} alla volta, eseguendo la lettura
+all'interno di un ciclo (\texttt{\small 8-24}) che prosegue fintanto che vi
+siano dati da leggere.
+
+Per questo ad ogni lettura si esamina (\texttt{\small 9-14}) se il valore di
+ritorno della funzione \func{read} è negativo, uscendo dal programma
+(\texttt{\small 11}) in caso di errore reale, o terminando il ciclo
+(\texttt{\small 13}) con un \texttt{break} qualora si ottenga un errore di
+\errcode{EAGAIN} per via dell'esaurimento dei dati. Si ricordi infatti come
+sia la \textit{fifo} che il file descriptor per i segnali siano stati aperti in
+modalità non-bloccante, come previsto per l’\textit{I/O multiplexing},
+pertanto ci si aspetta di ricevere un errore di \errcode{EAGAIN} quando non vi
+saranno più dati da leggere.
+
+In presenza di dati invece il programma proseguirà l'esecuzione stampando
+(\texttt{\small 19-20}) il nome del segnale ottenuto all'interno della
+struttura \struct{signalfd\_siginfo} letta in \var{siginf} ed il \textit{pid}
+del processo da cui lo ha ricevuto;\footnote{per la stampa si è usato il
+  vettore \var{sig\_names} a ciascun elemento del quale corrisponde il nome
+  del segnale avente il numero corrispondente, la cui definizione si è omessa
+  dal codice di fig.~\ref{fig:fiforeporter_code_init} per brevità.} inoltre
+(\texttt{\small 21-24}) si controllerà anche se il segnale ricevuto è
+\signal{SIGINT}, che si è preso come segnale da utilizzare per la terminazione
+del programma, che verrà eseguita dopo aver rimosso il file della \textit{name
+  fifo}.
+Il secondo condizionale (\texttt{\small 26-39}) è invece relativo al caso in
+cui ci siano dati pronti in lettura sulla \textit{fifo} e che il file
+descriptor pronto corrisponda (\texttt{\small 26}) a \var{fifofd}. Di nuovo si
+effettueranno le letture in un ciclo (\texttt{\small 28-39}) ripetendole fin
+tanto che la funzione \func{read} non restituisce un errore di
+\errcode{EAGAIN} (\texttt{\small 29-35}). Il procedimento è lo stesso adottato
+per il file descriptor associato al segnale, in cui si esce dal programma in
+caso di errore reale, in questo caso però alla fine dei dati prima di uscire
+si stampa anche (\texttt{\small 32}) un messaggio di chiusura.
+
+Se invece vi sono dati validi letti dalla \textit{fifo} si inserirà
+(\texttt{\small 36}) una terminazione di stringa sul buffer e si stamperà il
+tutto (\texttt{\small 37-38}) sullo \textit{standard output}. L'ultimo
+condizionale (\texttt{\small 40-44}) è semplicemente una condizione di cattura
+per una eventualità che comunque non dovrebbe mai verificarsi, e che porta
+alla uscita dal programma con una opportuna segnalazione di errore.
+
+A questo punto si potrà eseguire il comando lanciandolo su un terminale, ed
+osservarne le reazioni agli eventi generati da un altro terminale; lanciando
+il programma otterremo qualcosa del tipo:
+\begin{Console}
+piccardi@hain:~/gapil/sources$ \textbf{./a.out} 
+FifoReporter starting, pid 4568
+\end{Console}
+%$
+e scrivendo qualcosa sull'altro terminale con:
+\begin{Console}
+root@hain:~# \textbf{echo prova > /tmp/reporter.fifo}  
+\end{Console}
+si otterrà:
+\begin{Console}
+Message from fifo:
+prova
+end message
+\end{Console}
+mentre inviando un segnale:
+\begin{Console}
+root@hain:~# \textbf{kill 4568}
+\end{Console}
+si avrà:
+\begin{Console}
+Signal received:
+Got SIGTERM       
+From pid 3361
+\end{Console}
+ed infine premendo \texttt{C-\bslash} sul terminale in cui è in esecuzione si
+vedrà:
+\begin{Console}
+^\\Signal received:
+Got SIGQUIT       
+From pid 0
+\end{Console}
+e si potrà far uscire il programma con \texttt{C-c} ottenendo:
+\begin{Console}
+^CSignal received:
+Got SIGINT        
+From pid 0
+SIGINT means exit
+\end{Console}
+
+Lo stesso paradigma di notifica tramite file descriptor usato per i segnali è
+stato adottato anche per i timer. In questo caso, rispetto a quanto visto in
+sez.~\ref{sec:sig_timer_adv}, la scadenza di un timer potrà essere letta da un
+file descriptor senza dover ricorrere ad altri meccanismi di notifica come un
+segnale o un \textit{thread}. Di nuovo questo ha il vantaggio di poter
+utilizzare le funzioni dell'\textit{I/O multiplexing} per attendere allo
+stesso tempo la disponibilità di dati o la ricezione della scadenza di un
+timer. In realtà per questo sarebbe già sufficiente \func{signalfd} per
+ricevere i segnali associati ai timer, ma la nuova interfaccia semplifica
+notevolmente la gestione e consente di fare tutto con una sola \textit{system
+  call}.
+
+Le funzioni di questa nuova interfaccia ricalcano da vicino la struttura delle
+analoghe versioni ordinarie introdotte con lo standard POSIX.1-2001, che
+abbiamo già illustrato in sez.~\ref{sec:sig_timer_adv}.\footnote{questa
+  interfaccia è stata introdotta in forma considerata difettosa con il kernel
+  2.6.22, per cui è stata immediatamente tolta nel successivo 2.6.23 e
+  reintrodotta in una forma considerata adeguata nel kernel 2.6.25, il
+  supporto nelle \acr{glibc} è stato introdotto a partire dalla versione
+  2.8.6, la versione del kernel 2.6.22, presente solo su questo kernel, non è
+  supportata e non deve essere usata.} La prima funzione di sistema prevista,
+quella che consente di creare un timer, è \funcd{timerfd\_create}, il cui
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/timerfd.h}
+\fdecl{int timerfd\_create(int clockid, int flags)}
+
+\fdesc{Crea un timer associato ad un file descriptor di notifica.}
+}
+
+{La funzione ritorna un numero di file descriptor in caso di successo e $-1$
+  per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EINVAL}] l'argomento \param{clockid} non è
+    \const{CLOCK\_MONOTONIC} o \const{CLOCK\_REALTIME}, o
+    l'argomento \param{flag} non è valido, o è diverso da zero per kernel
+    precedenti il 2.6.27.
+  \item[\errcode{ENODEV}] il kernel non può montare internamente il
+    dispositivo per la gestione anonima degli \textit{inode} associati al file
+    descriptor.
+  \item[\errcode{ENOMEM}] non c'è memoria sufficiente per creare un nuovo file
+    descriptor di \func{signalfd}.
+  \end{errlist}
+  ed inoltre \errval{EMFILE} e \errval{ENFILE} nel loro significato generico.
+}  
+\end{funcproto}
+
+La funzione prende come primo argomento un intero che indica il tipo di
+orologio a cui il timer deve fare riferimento, i valori sono gli stessi delle
+funzioni dello standard POSIX-1.2001 già illustrati in
+tab.~\ref{tab:sig_timer_clockid_types}, ma al momento i soli utilizzabili sono
+\const{CLOCK\_REALTIME} e \const{CLOCK\_MONOTONIC}. L'argomento \param{flags},
+come l'analogo di \func{signalfd}, consente di impostare i flag per l'I/O non
+bloccante ed il \textit{close-on-exec} sul file descriptor
+restituito,\footnote{il flag è stato introdotto a partire dal kernel 2.6.27,
+  per le versioni precedenti deve essere passato un valore nullo.} e deve
+essere specificato come una maschera binaria delle costanti riportate in
+tab.~\ref{tab:timerfd_flags}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{TFD\_NONBLOCK}& imposta sul file descriptor il flag di
+                            \const{O\_NONBLOCK} per renderlo non bloccante.\\ 
+    \constd{TFD\_CLOEXEC} & imposta il flag di \const{O\_CLOEXEC} per la
+                            chiusura automatica del file descriptor nella
+                            esecuzione di \func{exec}.\\
+    \hline    
+  \end{tabular}
+  \caption{Valori dell'argomento \param{flags} per la funzione
+    \func{timerfd\_create} che consentono di impostare i flag del file
+    descriptor.}  
+  \label{tab:timerfd_flags}
+\end{table}
+
+In caso di successo la funzione restituisce un file descriptor sul quale
+verranno notificate le scadenze dei timer. Come per quelli restituiti da
+\func{signalfd} anche questo file descriptor segue la semantica dei sistemi
+unix-like, in particolare resta aperto attraverso una \func{exec} (a meno che
+non si sia impostato il flag di \textit{close-on exec} con
+\const{TFD\_CLOEXEC}) e viene duplicato attraverso una \func{fork}; questa
+ultima caratteristica comporta però che anche il figlio può utilizzare i dati
+di un timer creato nel padre, a differenza di quanto avviene invece con i
+timer impostati con le funzioni ordinarie. Si ricordi infatti che, come
+illustrato in sez.~\ref{sec:proc_fork}, allarmi, timer e segnali pendenti nel
+padre vengono cancellati per il figlio dopo una \func{fork}.
+
+Una volta creato il timer con \func{timerfd\_create} per poterlo utilizzare
+occorre \textsl{armarlo} impostandone un tempo di scadenza ed una eventuale
+periodicità di ripetizione, per farlo si usa una funzione di sistema omologa
+di \func{timer\_settime} per la nuova interfaccia; questa è
+\funcd{timerfd\_settime} ed il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/timerfd.h}
+\fdecl{int timerfd\_settime(int fd, int flags,
+                           const struct itimerspec *new\_value,\\
+\phantom{int timerfd\_settime(}struct itimerspec *old\_value)}
+
+\fdesc{Arma un timer associato ad un file descriptor di notifica.}
+}
+
+{La funzione ritorna un numero di file descriptor in caso di successo e $-1$
+  per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] l'argomento \param{fd} non corrisponde ad un file
+    descriptor. 
+  \item[\errcode{EFAULT}] o \param{new\_value} o \param{old\_value} non sono
+    puntatori validi.
+  \item[\errcode{EINVAL}] il file descriptor \param{fd} non è stato ottenuto
+    con \func{timerfd\_create}, o i valori di \param{flag} o dei campi
+    \var{tv\_nsec} in \param{new\_value} non sono validi.
+  \end{errlist}
+}  
+\end{funcproto}
+
+In questo caso occorre indicare su quale timer si intende operare specificando
+come primo argomento il file descriptor ad esso associato, che deve essere
+stato ottenuto da una precedente chiamata a \func{timerfd\_create}. I restanti
+argomenti sono del tutto analoghi a quelli della omologa funzione
+\func{timer\_settime}, e prevedono l'uso di strutture \struct{itimerspec}
+(vedi fig.~\ref{fig:struct_itimerspec}) per le indicazioni di temporizzazione.
+
+I valori ed il significato di questi argomenti sono gli stessi che sono già
+stati illustrati in dettaglio in sez.~\ref{sec:sig_timer_adv} e non staremo a
+ripetere quanto detto in quell'occasione; per brevità si ricordi che
+con \param{new\_value.it\_value} si indica la prima scadenza del timer e
+con \param{new\_value.it\_interval} la sua periodicità.  L'unica differenza
+riguarda l'argomento \param{flags} che serve sempre ad indicare se il tempo di
+scadenza del timer è da considerarsi relativo o assoluto rispetto al valore
+corrente dell'orologio associato al timer, ma che in questo caso ha come
+valori possibili rispettivamente soltanto $0$ e \constd{TFD\_TIMER\_ABSTIME}
+(l'analogo di \const{TIMER\_ABSTIME}).
+
+L'ultima funzione di sistema prevista dalla nuova interfaccia è
+\funcd{timerfd\_gettime}, che è l'analoga di \func{timer\_gettime}, il suo
+prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/timerfd.h}
+\fdecl{int timerfd\_gettime(int fd, struct itimerspec *curr\_value)}
+
+\fdesc{Legge l'impostazione di un timer associato ad un file descriptor di
+  notifica.} 
+}
+
+{La funzione ritorna un numero di file descriptor in caso di successo e $-1$
+  per un errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] l'argomento \param{fd} non corrisponde ad un file
+    descriptor. 
+  \item[\errcode{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{funcproto}
+
+La funzione consente di rileggere le impostazioni del timer associato al file
+descriptor \param{fd} nella struttura \struct{itimerspec} puntata
+da \param{curr\_value}. Il campo \var{it\_value} riporta il tempo rimanente
+alla prossima scadenza del timer, che viene sempre espresso in forma relativa,
+anche se lo si è armato specificando \const{TFD\_TIMER\_ABSTIME}. Un valore
+nullo (di entrambi i campi di \var{it\_value}) indica invece che il timer non
+è stato ancora armato. Il campo \var{it\_interval} riporta la durata
+dell'intervallo di ripetizione del timer, ed un valore nullo (di entrambi i
+campi) indica che il timer è stato impostato per scadere una sola volta.
+
+Il timer creato con \func{timerfd\_create} notificherà la sua scadenza
+rendendo pronto per la lettura il file descriptor ad esso associato, che
+pertanto potrà essere messo sotto controllo con una qualunque delle varie
+funzioni dell'I/O multiplexing viste in precedenza. Una volta che il file
+descriptor risulta pronto sarà possibile leggere il numero di volte che il
+timer è scaduto con una ordinaria \func{read}. 
+
+La funzione legge il valore in un dato di tipo \typed{uint64\_t}, e necessita
+pertanto che le si passi un buffer di almeno 8 byte, fallendo con
+\errval{EINVAL} in caso contrario, in sostanza la lettura deve essere
+effettuata con una istruzione del tipo:
+\includecodesnip{listati/readtimerfd.c} 
+
+Il valore viene restituito da \func{read} seguendo l'ordinamento dei bit
+(\textit{big-endian} o \textit{little-endian}) nativo della macchina in uso,
+ed indica il numero di volte che il timer è scaduto dall'ultima lettura
+eseguita con successo, o, se lo si legge per la prima volta, da quando lo si è
+impostato con \func{timerfd\_settime}. Se il timer non è scaduto la funzione
+si blocca fino alla prima scadenza, a meno di non aver creato il file
+descriptor in modalità non bloccante con \const{TFD\_NONBLOCK} o aver
+impostato la stessa con \func{fcntl}, nel qual caso fallisce con l'errore di
+\errval{EAGAIN}.
+
+
+% TODO trattare qui eventfd introdotto con il 2.6.22 
+
+
+\section{L'accesso \textsl{asincrono} ai file}
+\label{sec:file_asyncronous_operation}
+
+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, ma esistono anche altre interfacce, come \textit{inotify}),
+per essere avvisato della possibilità di eseguire le operazioni di I/O volute.
+
+
+\subsection{Il \textit{Signal driven I/O}}
+\label{sec:signal_driven_io}
+
+\itindbeg{signal~driven~I/O}
+
+Abbiamo accennato in sez.~\ref{sec:file_open_close} che è definito un flag
+\const{O\_ASYNC}, che consentirebbe di aprire un file in modalità asincrona,
+anche se in realtà è opportuno 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_ioctl}).\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.}  In realtà parlare di apertura
+in modalità asincrona non significa che le operazioni di lettura o scrittura
+del file vengono eseguite in modo asincrono (tratteremo questo, che è ciò che
+più propriamente viene chiamato \textsl{I/O asincrono}, in
+sez.~\ref{sec:file_asyncronous_io}), quanto dell'attivazione un meccanismo di
+notifica asincrona delle variazione dello stato del file descriptor aperto in
+questo modo.
+
+Quello che succede è che per tutti i file posti in questa modalità il sistema
+genera un apposito segnale, \signal{SIGIO}, tutte le volte che diventa
+possibile leggere o scrivere dal file descriptor; si tenga presente però che
+essa non è utilizzabile con i file ordinari ma solo con socket, file di
+terminale o pseudo terminale, ed anche, a partire dal kernel 2.6, per
+\textit{fifo} e \textit{pipe}. Inoltre è possibile, come illustrato in
+sez.~\ref{sec:file_fcntl_ioctl}, selezionare con il comando \const{F\_SETOWN}
+di \func{fcntl} quale processo o quale gruppo di processi dovrà ricevere il
+segnale. In questo modo diventa possibile effettuare le operazioni di I/O in
+risposta alla ricezione del segnale, e non ci sarà più la necessità di restare
+bloccati in attesa della disponibilità di accesso ai file.
+
+% TODO: per i thread l'uso di F_SETOWN ha un significato diverso
+
+Per questo motivo Stevens, ed anche le pagine di manuale di Linux, chiamano
+questa modalità ``\textit{Signal driven I/O}''.  Si tratta di un'altra
+modalità di gestione dell'I/O, alternativa all'uso di
+\textit{epoll},\footnote{anche se le prestazioni ottenute con questa tecnica
+  sono inferiori, il vantaggio è che questa modalità è utilizzabile anche con
+  kernel che non supportano \textit{epoll}, come quelli della serie 2.4,
+  ottenendo comunque prestazioni superiori a quelle che si hanno con
+  \func{poll} e \func{select}.} che consente di evitare l'uso delle funzioni
+\func{poll} o \func{select} che, come illustrato in sez.~\ref{sec:file_epoll},
+quando vengono usate con un numero molto grande di file descriptor, non hanno
+buone prestazioni.
+
+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 \textit{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
+\textit{real-time} (vedi sez.~\ref{sec:sig_real_time}) impostando
+esplicitamente con il comando \const{F\_SETSIG} di \func{fcntl} un segnale
+\textit{real-time} da inviare in caso di I/O asincrono (il segnale predefinito
+è \signal{SIGIO}). In questo caso il gestore, tutte le volte che riceverà
+\const{SI\_SIGIO} come valore del campo \var{si\_code} di \struct{siginfo\_t},
+troverà nel campo \var{si\_fd} il valore del file descriptor che ha generato
+il segnale. Si noti che il valore di\var{si\_code} resta \const{SI\_SIGIO}
+qualunque sia il segnale che si è associato all'I/O, in quanto indica che il
+segnale è stato generato a causa di attività di I/O.
+
+Un secondo vantaggio dell'uso dei segnali \textit{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
+\textit{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 \textit{real-time},
+invierà al suo posto un solo \signal{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. L'unico modo per essere sicuri che questo non
+avvenga è di impostare la lunghezza della coda dei segnali \textit{real-time}
+ad una dimensione identica al valore massimo del numero di file descriptor
+utilizzabili, vale a dire impostare il contenuto di
+\sysctlfile{kernel/rtsig-max} allo stesso valore del contenuto di
+\sysctlfile{fs/file-max}.
+
+% TODO fare esempio che usa O_ASYNC
+
+\itindend{signal~driven~I/O}
+
+
+
+\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, 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 classico non prevedeva
+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 se il loro file di configurazione è stato modificato, perché possano
+rileggerlo e riconoscere le modifiche; in genere questo vien fatto inviandogli
+un segnale di \signal{SIGHUP} che, per una convenzione adottata dalla gran
+parte di detti programmi, causa la rilettura della configurazione.
+
+Questa scelta è stata fatta perché provvedere un simile meccanismo a livello
+generico per qualunque file comporterebbe un notevole aumento di complessità
+dell'architettura della gestione dei file, il tutto per fornire una
+funzionalità che serve soltanto in alcuni 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 \textit{user space}, non era stata
+prevista nessuna funzionalità di notifica.
+
+Visto però il crescente interesse nei confronti di una funzionalità di questo
+tipo, che è molto richiesta specialmente nello sviluppo dei programmi ad
+interfaccia grafica quando si deve presentare all'utente lo stato del
+filesystem, 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
+\textit{polling}.
+
+Queste nuove funzionalità sono delle estensioni specifiche, non
+standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel
+supportano meccanismi simili). Alcune di 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_ioctl}), che divengono disponibili soltanto se si è
+definita la macro \macro{\_GNU\_SOURCE} prima di includere \headfile{fcntl.h}.
+
+\itindbeg{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 \signal{SIGIO}, ma questo segnale può essere
+modificato usando il comando \const{F\_SETSIG} di \func{fcntl} (anche in
+questo caso si può rispecificare lo stesso \signal{SIGIO}).
+
+Se si è fatto questo (ed in genere è opportuno farlo, come in precedenza, per
+utilizzare segnali \textit{real-time}) e se inoltre si è installato il gestore
+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 in 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_ioctl} 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
+    \constd{F\_RDLCK} & Richiede un \textit{read lease}.\\
+    \constd{F\_WRLCK} & Richiede un \textit{write lease}.\\
+    \constd{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
+(\textit{pipe} e dispositivi sono quindi esclusi). Inoltre un processo non
+privilegiato può ottenere un \textit{lease} soltanto per un file appartenente
+ad un \ids{UID} corrispondente a quello del processo. Soltanto un processo con
+privilegi di amministratore (cioè con la capacità \const{CAP\_LEASE}, vedi
+sez.~\ref{sec:proc_capabilities}) 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
@@ -30,7 +2875,7 @@ operazione di lettura, declassando il \textit{lease} a lettura con
 
 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
+\sysctlfiled{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
@@ -74,26 +2919,26 @@ che è stato modificato tramite il contenuto della struttura
     \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.\\ 
+    \constd{DN\_ACCESS} & Un file è stato acceduto, con l'esecuzione di una fra
+                          \func{read}, \func{pread}, \func{readv}.\\ 
+    \constd{DN\_MODIFY} & Un file è stato modificato, con l'esecuzione di una
+                          fra \func{write}, \func{pwrite}, \func{writev}, 
+                          \func{truncate}, \func{ftruncate}.\\ 
+    \constd{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).\\
+    \constd{DN\_DELETE} & È stato cancellato un file dalla directory con
+                          l'esecuzione di una fra \func{unlink}, \func{rename}
+                          (su un'altra directory), \func{rmdir}.\\
+    \constd{DN\_RENAME} & È stato rinominato un file all'interno della
+                          directory (con \func{rename}).\\
+    \constd{DN\_ATTRIB} & È stato modificato un attributo di un file con
+                          l'esecuzione di una fra \func{chown}, \func{chmod},
+                          \func{utime}.\\ 
+    \constd{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
@@ -149,9 +2994,8 @@ interfaccia per l'osservazione delle modifiche a file o directory, chiamata
 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 è:
+di risolvere il principale problema di \textit{dnotify}.  La coda viene creata
+attraverso la funzione di sistema \funcd{inotify\_init}, il cui prototipo è:
 
 \begin{funcproto}{
 \fhead{sys/inotify.h}
@@ -180,7 +3024,7 @@ 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}.
+\sysctlfiled{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
@@ -192,10 +3036,9 @@ 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. 
+introdotto anche il supporto per il \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
@@ -243,7 +3086,7 @@ 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
+  \sysctlfiled{fs/inotify/max\_user\_watches}.} e si utilizzerà sempre un solo
 file descriptor.
 
 Il tipo di evento che si vuole osservare deve essere specificato
@@ -263,41 +3106,41 @@ flag della prima parte.
     \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
+    \constd{IN\_ACCESS}        &$\bullet$& C'è stato accesso al file in
+                                           lettura.\\  
+    \constd{IN\_ATTRIB}        &$\bullet$& Ci sono stati cambiamenti sui dati
+                                           dell'\textit{inode}
+                                           (o sugli attributi estesi, vedi
+                                           sez.~\ref{sec:file_xattr}).\\ 
+    \constd{IN\_CLOSE\_WRITE}  &$\bullet$& È stato chiuso un file aperto in
+                                           scrittura.\\  
+    \constd{IN\_CLOSE\_NOWRITE}&$\bullet$& È stato chiuso un file aperto in
+                                           sola lettura.\\
+    \constd{IN\_CREATE}        &$\bullet$& È stato creato un file o una
+                                           directory in una directory sotto
+                                           osservazione.\\  
+    \constd{IN\_DELETE}        &$\bullet$& È stato cancellato un file o una
+                                           directory in una directory sotto
+                                           osservazione.\\ 
+    \constd{IN\_DELETE\_SELF}  & --      & È stato cancellato 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.\\ 
+    \constd{IN\_MODIFY}        &$\bullet$& È stato modificato il file.\\ 
+    \constd{IN\_MOVE\_SELF}    &         & È stato rinominato il file (o la
+                                           directory) sotto osservazione.\\ 
+    \constd{IN\_MOVED\_FROM}   &$\bullet$& Un file è stato spostato fuori dalla
+                                           directory sotto osservazione.\\ 
+    \constd{IN\_MOVED\_TO}     &$\bullet$& Un file è stato spostato nella
+                                           directory sotto osservazione.\\ 
+    \constd{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.\\
+    \constd{IN\_CLOSE}         &         & Combinazione di
+                                           \const{IN\_CLOSE\_WRITE} e
+                                           \const{IN\_CLOSE\_NOWRITE}.\\  
+    \constd{IN\_MOVE}          &         & Combinazione di
+                                           \const{IN\_MOVED\_FROM} e
+                                           \const{IN\_MOVED\_TO}.\\
+    \constd{IN\_ALL\_EVENTS}   &         & Combinazione di tutti i flag
+                                           possibili.\\
     \hline    
   \end{tabular}
   \caption{Le costanti che identificano i bit della maschera binaria
@@ -324,17 +3167,17 @@ contrario dei precedenti non vengono mai impostati nei risultati in uscita.
     \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.\\ 
+    \constd{IN\_DONT\_FOLLOW}& Non dereferenzia \param{pathname} se questo è un
+                               link simbolico.\\
+    \constd{IN\_MASK\_ADD}   & Aggiunge a quelli già impostati i flag indicati
+                               nell'argomento \param{mask}, invece di
+                               sovrascriverli.\\
+    \constd{IN\_ONESHOT}     & Esegue l'osservazione su \param{pathname} per
+                               una sola volta, rimuovendolo poi dalla
+                               \textit{watch list}.\\ 
+    \constd{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
@@ -456,21 +3299,21 @@ registrazione dell'osservatore).
     \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.\\
+    \constd{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.\\
+    \constd{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).\\
+    \constd{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\\
+    \constd{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
@@ -480,7 +3323,7 @@ registrazione dell'osservatore).
 
 \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
+  \sysctlfiled{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}.}
@@ -494,15 +3337,15 @@ così all'applicazione di collegare la corrispondente coppia di eventi
 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}.
+(come \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
@@ -652,21 +3495,21 @@ 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.
+sono \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 \textit{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 \textit{user space}, ed è accessibile linkando i programmi con la libreria
+l'uso di \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 \textit{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.
@@ -675,9 +3518,9 @@ 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
+effettuata in \headfiled{aio.h}, è riportata in
 fig.~\ref{fig:file_aiocb}. Nello steso file è definita la macro
-\macro{\_POSIX\_ASYNCHRONOUS\_IO}, che dichiara la disponibilità
+\macrod{\_POSIX\_ASYNCHRONOUS\_IO}, che dichiara la disponibilità
 dell'interfaccia per l'I/O asincrono.
 
 \begin{figure}[!htb]
@@ -707,8 +3550,8 @@ 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
+\macrod{\_POSIX\_PRIORITIZED\_IO}, e \macrod{\_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
@@ -901,13 +3744,13 @@ 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
+\item[\constd{AIO\_ALLDONE}] indica che le operazioni di cui si è richiesta la
   cancellazione sono state già completate,
   
-\item[\const{AIO\_CANCELED}] indica che tutte le operazioni richieste sono
+\item[\constd{AIO\_CANCELED}] indica che tutte le operazioni richieste sono
   state cancellate,  
   
-\item[\const{AIO\_NOTCANCELED}] indica che alcune delle operazioni erano in
+\item[\constd{AIO\_NOTCANCELED}] indica che alcune delle operazioni erano in
   corso e non sono state cancellate.
 \end{basedescript}
 
@@ -995,9 +3838,9 @@ Ciascuna struttura \struct{aiocb} della lista deve contenere un
 ognuna di esse dovrà essere specificato il tipo di operazione con il campo
 \var{aio\_lio\_opcode}, che può prendere i valori:
 \begin{basedescript}{\desclabelwidth{2.0cm}}
-\item[\const{LIO\_READ}]  si richiede una operazione di lettura.
-\item[\const{LIO\_WRITE}] si richiede una operazione di scrittura.
-na operazione.
+\item[\constd{LIO\_READ}]  si richiede una operazione di lettura.
+\item[\constd{LIO\_WRITE}] si richiede una operazione di scrittura.
+\item[\constd{LIO\_NOP}] non si effettua nessuna operazione.
 \end{basedescript}
 dove \const{LIO\_NOP} viene usato quando si ha a che fare con un vettore di
 dimensione fissa, per poter specificare solo alcune operazioni, o quando si
@@ -1005,8 +3848,8 @@ sono dovute cancellare delle operazioni e si deve ripetere la richiesta per
 quelle non completate. 
 
 L'argomento \param{mode} controlla il comportamento della funzione, se viene
-usato il valore \const{LIO\_WAIT} la funzione si blocca fino al completamento
-di tutte le operazioni richieste; se si usa \const{LIO\_NOWAIT} la funzione
+usato il valore \constd{LIO\_WAIT} la funzione si blocca fino al completamento
+di tutte le operazioni richieste; se si usa \constd{LIO\_NOWAIT} la funzione
 ritorna immediatamente dopo aver messo in coda tutte le richieste. In tal caso
 il chiamante può richiedere la notifica del completamento di tutte le
 richieste, impostando l'argomento \param{sig} in maniera analoga a come si fa
@@ -1017,6 +3860,7 @@ per il campo \var{aio\_sigevent} di \struct{aiocb}.
 % http://webfiveoh.com/content/guides/2012/aug/mon-13th/linux-asynchronous-io-and-libaio.html, 
 % https://code.google.com/p/kernel/wiki/AIOUserGuide,
 % http://bert-hubert.blogspot.de/2012/05/on-linux-asynchronous-file-io.html 
+% https://www.fsl.cs.sunysb.edu/~vass/linux-aio.txt
 
 
 \section{Altre modalità di I/O avanzato}
@@ -1035,10 +3879,11 @@ avanzato.
 \label{sec:file_memory_map}
 
 \itindbeg{memory~mapping}
+
 Una modalità alternativa di I/O, che usa una interfaccia completamente diversa
 rispetto a quella classica vista in sez.~\ref{sec:file_unix_interface}, è il
 cosiddetto \textit{memory-mapped I/O}, che attraverso il meccanismo della
-\textsl{paginazione} \index{paginazione} usato dalla memoria virtuale (vedi
+\textsl{paginazione}  usato dalla memoria virtuale (vedi
 sez.~\ref{sec:proc_mem_gen}) permette di \textsl{mappare} il contenuto di un
 file in una sezione dello spazio di indirizzi del processo che lo ha allocato.
 
@@ -1150,10 +3995,10 @@ memoria.
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \const{PROT\_EXEC}  & Le pagine possono essere eseguite.\\
-    \const{PROT\_READ}  & Le pagine possono essere lette.\\
-    \const{PROT\_WRITE} & Le pagine possono essere scritte.\\
-    \const{PROT\_NONE}  & L'accesso alle pagine è vietato.\\
+    \constd{PROT\_EXEC}  & Le pagine possono essere eseguite.\\
+    \constd{PROT\_READ}  & Le pagine possono essere lette.\\
+    \constd{PROT\_WRITE} & Le pagine possono essere scritte.\\
+    \constd{PROT\_NONE}  & L'accesso alle pagine è vietato.\\
     \hline    
   \end{tabular}
   \caption{Valori dell'argomento \param{prot} di \func{mmap}, relativi alla
@@ -1182,53 +4027,53 @@ file.
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \const{MAP\_32BIT}     & Esegue la mappatura sui primi 2Gb dello spazio
+    \constd{MAP\_32BIT}    & Esegue la mappatura sui primi 2Gb dello spazio
                              degli indirizzi, viene supportato solo sulle
                              piattaforme \texttt{x86-64} per compatibilità con
                              le applicazioni a 32 bit. Viene ignorato se si è
                              richiesto \const{MAP\_FIXED} (dal kernel 2.4.20).\\
-    \const{MAP\_ANON}      & Sinonimo di \const{MAP\_ANONYMOUS}, deprecato.\\
-    \const{MAP\_ANONYMOUS} & La mappatura non è associata a nessun file. Gli
+    \constd{MAP\_ANON}     & Sinonimo di \const{MAP\_ANONYMOUS}, deprecato.\\
+    \constd{MAP\_ANONYMOUS}& La mappatura non è associata a nessun file. Gli
                              argomenti \param{fd} e \param{offset} sono
                              ignorati. L'uso di questo flag con
                              \const{MAP\_SHARED} è stato implementato in Linux
                              a partire dai kernel della serie 2.4.x.\\
-    \const{MAP\_DENYWRITE} & In Linux viene ignorato per evitare
+    \constd{MAP\_DENYWRITE}& In Linux viene ignorato per evitare
                              \textit{DoS}
                              (veniva usato per segnalare che tentativi di
                              scrittura sul file dovevano fallire con
                              \errcode{ETXTBSY}).\\ 
-    \const{MAP\_EXECUTABLE}& Ignorato.\\
-    \const{MAP\_FILE}      & Valore di compatibilità, ignorato.\\
-    \const{MAP\_FIXED}     & Non permette di restituire un indirizzo diverso
+    \constd{MAP\_EXECUTABLE}& Ignorato.\\
+    \constd{MAP\_FILE}     & Valore di compatibilità, ignorato.\\
+    \constd{MAP\_FIXED}    & Non permette di restituire un indirizzo diverso
                              da \param{start}, se questo non può essere usato
                              \func{mmap} fallisce. Se si imposta questo flag il
                              valore di \param{start} deve essere allineato
                              alle dimensioni di una pagina.\\
-    \const{MAP\_GROWSDOWN} & Usato per gli \textit{stack}. 
+    \constd{MAP\_GROWSDOWN}& Usato per gli \textit{stack}. 
                              Indica che la mappatura deve essere effettuata 
                              con gli indirizzi crescenti verso il basso.\\
-    \const{MAP\_HUGETLB}   & Esegue la mappatura usando le cosiddette
+    \constd{MAP\_HUGETLB}  & Esegue la mappatura usando le cosiddette
                              ``\textit{huge pages}'' (dal kernel 2.6.32).\\
-    \const{MAP\_LOCKED}    & Se impostato impedisce lo \textit{swapping} delle
+    \constd{MAP\_LOCKED}   & Se impostato impedisce lo \textit{swapping} delle
                              pagine mappate (dal kernel 2.5.37).\\
-    \const{MAP\_NONBLOCK}  & Esegue un \textit{prefaulting} più limitato che
+    \constd{MAP\_NONBLOCK} & Esegue un \textit{prefaulting} più limitato che
                              non causa I/O (dal kernel 2.5.46).\\
-    \const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva
+    \constd{MAP\_NORESERVE}& Si usa con \const{MAP\_PRIVATE}. Non riserva
                              delle pagine di \textit{swap} ad uso del meccanismo
                              del \textit{copy on write} 
                              per mantenere le modifiche fatte alla regione
                              mappata, in questo caso dopo una scrittura, se
                              non c'è più memoria disponibile, si ha
                              l'emissione di un \signal{SIGSEGV}.\\
-    \const{MAP\_POPULATE}  & Esegue il \textit{prefaulting} delle pagine di
+    \constd{MAP\_POPULATE} & Esegue il \textit{prefaulting} delle pagine di
                              memoria necessarie alla mappatura (dal kernel
                              2.5.46).\\ 
-    \const{MAP\_PRIVATE}   & I cambiamenti sulla memoria mappata non vengono
+    \constd{MAP\_PRIVATE}  & I cambiamenti sulla memoria mappata non vengono
                              riportati sul file. Ne viene fatta una copia
                              privata cui solo il processo chiamante ha
                              accesso.  Incompatibile con \const{MAP\_SHARED}.\\
-    \const{MAP\_SHARED}    & I cambiamenti sulla memoria mappata vengono
+    \constd{MAP\_SHARED}   & I cambiamenti sulla memoria mappata vengono
                              riportati sul file e saranno immediatamente
                              visibili agli altri processi che mappano lo stesso
                              file. Incompatibile
@@ -1239,7 +4084,7 @@ file.
                              uno spazio utilizzabile come \textit{stack} per le
                              architetture hardware che richiedono un
                              trattamento speciale di quest'ultimo.\\
-    \const{MAP\_UNINITIALIZED}& Specifico per i sistemi embedded ed
+    \constd{MAP\_UNINITIALIZED}& Specifico per i sistemi embedded ed
                              utilizzabile dal kernel 2.6.33 solo se è stata
                              abilitata in fase di compilazione dello stesso
                              l'opzione
@@ -1253,7 +4098,7 @@ file.
                              per i sistemi embedded) si ha il completo
                              controllo dell'uso della memoria da parte degli
                              utenti.\\ 
-%     \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
+%    \constd{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
 %                              mappata con \func{mremap}, proposto ma pare non
 %                              implementato.\\
     \hline
@@ -1265,6 +4110,9 @@ file.
 % TODO trattare MAP_HUGETLB introdotto con il kernel 2.6.32, e modifiche
 % introdotte con il 3.8 per le dimensioni variabili delle huge pages
 
+% TODO trattare  MAP_FIXED_NOREPLACE vedi https://lwn.net/Articles/751651/ e
+% https://lwn.net/Articles/741369/ 
+
 L'argomento \param{flags} specifica infine qual è il tipo di oggetto mappato,
 le opzioni relative alle modalità con cui è effettuata la mappatura e alle
 modalità con cui le modifiche alla memoria mappata vengono condivise o
@@ -1435,7 +4283,6 @@ relativi tempi di modifica. In questo modo si è sicuri che dopo l'esecuzione
 di \func{msync} le funzioni dell'interfaccia ordinaria troveranno un contenuto
 del file aggiornato.
 
-
 \begin{table}[htb]
   \centering
   \footnotesize
@@ -1444,11 +4291,11 @@ del file aggiornato.
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \const{MS\_SYNC}       & richiede una sincronizzazione e ritorna soltanto
+    \constd{MS\_SYNC}      & richiede una sincronizzazione e ritorna soltanto
                              quando questa è stata completata.\\
-    \const{MS\_ASYNC}      & richiede una sincronizzazione, ma ritorna subito 
+    \constd{MS\_ASYNC}     & richiede una sincronizzazione, ma ritorna subito 
                              non attendendo che questa sia finita.\\
-    \const{MS\_INVALIDATE} & invalida le pagine per tutte le mappature
+    \constd{MS\_INVALIDATE}& invalida le pagine per tutte le mappature
                              in memoria così da rendere necessaria una
                              rilettura immediata delle stesse.\\
     \hline
@@ -1570,7 +4417,7 @@ precedente indirizzo del \textit{memory mapping} e \param{old\_size}, che ne
 indica la dimensione. Con \param{new\_size} si specifica invece la nuova
 dimensione che si vuole ottenere. Infine l'argomento \param{flags} è una
 maschera binaria per i flag che controllano il comportamento della funzione.
-Il solo valore utilizzato è \const{MREMAP\_MAYMOVE} che consente di eseguire
+Il solo valore utilizzato è \constd{MREMAP\_MAYMOVE} che consente di eseguire
 l'espansione anche quando non è possibile utilizzare il precedente
 indirizzo. Per questo motivo, se si è usato questo flag, la funzione può
 restituire un indirizzo della nuova zona di memoria che non è detto coincida
@@ -1760,87 +4607,94 @@ caching dei dati.
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \const{MADV\_DONTNEED}& non ci si aspetta nessun accesso nell'immediato
-                            futuro, pertanto le pagine possono essere
-                            liberate dal kernel non appena necessario; l'area
-                            di memoria resterà accessibile, ma un accesso
-                            richiederà che i dati vengano ricaricati dal file
-                            a cui la mappatura fa riferimento.\\
-    \const{MADV\_NORMAL}  & nessuna indicazione specifica, questo è il valore
-                            di default usato quando non si è chiamato
-                            \func{madvise}.\\
-    \const{MADV\_RANDOM}  & ci si aspetta un accesso casuale all'area
-                            indicata, pertanto l'applicazione di una lettura
-                            anticipata con il meccanismo del
-                            \textit{read-ahead} (vedi 
-                            sez.~\ref{sec:file_fadvise}) è di
-                            scarsa utilità e verrà disabilitata.\\
-    \const{MADV\_SEQUENTIAL}& ci si aspetta un accesso sequenziale al file,
-                            quindi da una parte sarà opportuno eseguire una
-                            lettura anticipata, e dall'altra si potranno
-                            scartare immediatamente le pagine una volta che
-                            queste siano state lette.\\
+    \constd{MADV\_DONTNEED}& non ci si aspetta nessun accesso nell'immediato
+                             futuro, pertanto le pagine possono essere
+                             liberate dal kernel non appena necessario; l'area
+                             di memoria resterà accessibile, ma un accesso
+                             richiederà che i dati vengano ricaricati dal file
+                             a cui la mappatura fa riferimento.\\
+    \constd{MADV\_NORMAL}  & nessuna indicazione specifica, questo è il valore
+                             di default usato quando non si è chiamato
+                             \func{madvise}.\\
+    \constd{MADV\_RANDOM}  & ci si aspetta un accesso casuale all'area
+                             indicata, pertanto l'applicazione di una lettura
+                             anticipata con il meccanismo del
+                             \textit{read-ahead} (vedi 
+                             sez.~\ref{sec:file_fadvise}) è di
+                             scarsa utilità e verrà disabilitata.\\
+    \constd{MADV\_SEQUENTIAL}& ci si aspetta un accesso sequenziale al file,
+                               quindi da una parte sarà opportuno eseguire una
+                               lettura anticipata, e dall'altra si potranno
+                               scartare immediatamente le pagine una volta che
+                               queste siano state lette.\\
     \const{MADV\_WILLNEED}& ci si aspetta un accesso nell'immediato futuro,
                             pertanto l'applicazione del \textit{read-ahead}
                             deve essere incentivata.\\
     \hline
-    \const{MADV\_DONTDUMP}& esclude da un \textit{core dump} (vedi
-                            sez.~\ref{sec:sig_standard}) le pagine 
-                            specificate, viene usato per evitare di scrivere
-                            su disco dati relativi a zone di memoria che si sa
-                            non essere utili in un \textit{core dump}.\\
-    \const{MADV\_DODUMP}  & rimuove l'effetto della precedente
-                            \const{MADV\_DONTDUMP} (dal kernel 3.4).\\ 
-    \const{MADV\_DONTFORK}& impedisce che l'intervallo specificato venga
-                            ereditato dal processo figlio dopo una
-                            \func{fork}; questo consente di evitare che il
-                            meccanismo del \textit{copy on write} effettui la
-                            rilocazione delle pagine quando il padre scrive
-                            sull'area di memoria dopo la \func{fork}, cosa che
-                            può causare problemi per l'hardware che esegue
-                            operazioni in DMA su quelle pagine (dal kernel
-                            2.6.16).\\
-    \const{MADV\_DOFORK}  & rimuove l'effetto della precedente
-                            \const{MADV\_DONTFORK} (dal kernel 2.6.16).\\ 
-    \const{MADV\_HUGEPAGE}& abilita il meccanismo delle \textit{Transparent
-                              Huge Page} (vedi sez.~\ref{sec:huge_pages})
-                            sulla regione indicata; se questa è allineata
-                            alle relative dimensioni il kernel alloca
-                            direttamente delle \textit{huge page}; è
-                            utilizzabile solo con mappature anomime private
-                            (dal kernel 2.6.38).\\
-    \const{MADV\_NOHUGEPAGE}& impedisce che la regione indicata venga
-                            collassata in eventuali \textit{huge page} (dal
-                            kernel 2.6.38).\\
-    \const{MADV\_HWPOISON} &opzione ad uso di debug per verificare codice
-                            che debba gestire errori nella gestione della
-                            memoria; richiede una apposita opzione di
-                            compilazione del kernel, privilegi amministrativi
-                            (la capacità \const{CAP\_SYS\_ADMIN}) e provoca
-                            l'emissione di un segnale di \const{SIGBUS} dal
-                            programma chiamante e rimozione della mappatura
-                            (dal kernel 2.6.32).\\
-    \const{MADV\_SOFT\_OFFLINE}&opzione utilizzata per il debug del
-                            codice di verifica degli errori di gestione
-                            memoria, richiede una apposita opzione di
-                            compilazione (dal kernel 2.6.33).\\
-    \const{MADV\_MERGEABLE}& marca la pagina come accorpabile, indicazione
-                            principalmente ad uso dei sistemi di
-                            virtualizzazione\footnotemark (dal kernel 2.6.32).\\
-    \const{MADV\_REMOVE}  & libera un intervallo di pagine di memoria ed il
-                            relativo supporto sottostante; è supportato
-                            soltanto sui filesystem in RAM \textit{tmpfs} e
-                            \textit{shmfs} se usato su altri tipi di
-                            filesystem causa un errore di \errcode{ENOSYS}
-                            (dal kernel 2.6.16).\\
-    \const{MADV\_UNMERGEABLE}& rimuove l'effetto della precedente
-                            \const{MADV\_MERGEABLE} (dal kernel 2.6.32). \\
-     \hline
+    \constd{MADV\_DONTDUMP}& esclude da un \textit{core dump} (vedi
+                             sez.~\ref{sec:sig_standard}) le pagine 
+                             specificate, viene usato per evitare di scrivere
+                             su disco dati relativi a zone di memoria che si sa
+                             non essere utili in un \textit{core dump}.\\
+    \constd{MADV\_DODUMP}  & rimuove l'effetto della precedente
+                             \const{MADV\_DONTDUMP} (dal kernel 3.4).\\ 
+    \constd{MADV\_DONTFORK}& impedisce che l'intervallo specificato venga
+                             ereditato dal processo figlio dopo una
+                             \func{fork}; questo consente di evitare che il
+                             meccanismo del \textit{copy on write} effettui la
+                             rilocazione delle pagine quando il padre scrive
+                             sull'area di memoria dopo la \func{fork}, cosa che
+                             può causare problemi per l'hardware che esegue
+                             operazioni in DMA su quelle pagine (dal kernel
+                             2.6.16).\\
+    \constd{MADV\_DOFORK}  & rimuove l'effetto della precedente
+                             \const{MADV\_DONTFORK} (dal kernel 2.6.16).\\ 
+    \constd{MADV\_HUGEPAGE}& abilita il meccanismo delle \textit{Transparent
+                             Huge Page} (vedi sez.~\ref{sec:huge_pages})
+                             sulla regione indicata; se questa è allineata
+                             alle relative dimensioni il kernel alloca
+                             direttamente delle \textit{huge page}; è
+                             utilizzabile solo con mappature anomime private
+                             (dal kernel 2.6.38).\\
+    \constd{MADV\_NOHUGEPAGE}& impedisce che la regione indicata venga
+                               collassata in eventuali \textit{huge page} (dal
+                               kernel 2.6.38).\\
+    \constd{MADV\_HWPOISON} &opzione ad uso di debug per verificare codice
+                              che debba gestire errori nella gestione della
+                              memoria; richiede una apposita opzione di
+                              compilazione del kernel, privilegi amministrativi
+                              (la capacità \const{CAP\_SYS\_ADMIN}) e provoca
+                              l'emissione di un segnale di \const{SIGBUS} dal
+                              programma chiamante e rimozione della mappatura
+                              (dal kernel 2.6.32).\\
+    \constd{MADV\_SOFT\_OFFLINE}&opzione utilizzata per il debug del
+                              codice di verifica degli errori di gestione
+                              memoria, richiede una apposita opzione di
+                              compilazione (dal kernel 2.6.33).\\
+    \constd{MADV\_MERGEABLE}& marca la pagina come accorpabile, indicazione
+                              principalmente ad uso dei sistemi di
+                              virtualizzazione\footnotemark (dal kernel
+                              2.6.32).\\ 
+    \constd{MADV\_REMOVE}  & libera un intervallo di pagine di memoria ed il
+                             relativo supporto sottostante; è supportato
+                             soltanto sui filesystem in RAM \textit{tmpfs} e
+                             \textit{shmfs} se usato su altri tipi di
+                             filesystem causa un errore di \errcode{ENOSYS}
+                             (dal kernel 2.6.16).\\
+    \constd{MADV\_UNMERGEABLE}& rimuove l'effetto della precedente
+                                \const{MADV\_MERGEABLE} (dal kernel 2.6.32). \\
+    \hline
   \end{tabular}
   \caption{Valori dell'argomento \param{advice} di \func{madvise}.}
   \label{tab:madvise_advice_values}
 \end{table}
 
+% TODO aggiunta MADV_FREE dal kernel 4.5 (vedi http://lwn.net/Articles/590991/)
+% TODO aggiunta MADV_WIPEONFORK dal kernel 4.14 that causes the affected memory
+% region to appear to be full of zeros in the child process after a fork. It
+% differs from the existing MADV_DONTFORK in that the address range will
+% remain valid in the child (dalla notizia in https://lwn.net/Articles/733256/).  
+
 \footnotetext{a partire dal kernel 2.6.32 è stato introdotto un meccanismo che
   identifica pagine di memoria identiche e le accorpa in una unica pagina
   (soggetta al \textit{copy-on-write} per successive modifiche); per evitare
@@ -1896,11 +4750,11 @@ funzione, su Linux un valore nullo di \param{len} è consentito.
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \const{POSIX\_MADV\_DONTNEED}& analogo a \const{MADV\_DONTNEED}.\\
-    \const{POSIX\_MADV\_NORMAL}  & identico a \const{MADV\_NORMAL}.\\
-    \const{POSIX\_MADV\_RANDOM}  & identico a \const{MADV\_RANDOM}.\\
-    \const{POSIX\_MADV\_SEQUENTIAL}& identico a \const{MADV\_SEQUENTIAL}.\\
-    \const{POSIX\_MADV\_WILLNEED}& identico a \const{MADV\_WILLNEED}.\\
+    \constd{POSIX\_MADV\_DONTNEED}& analogo a \const{MADV\_DONTNEED}.\\
+    \constd{POSIX\_MADV\_NORMAL}  & identico a \const{MADV\_NORMAL}.\\
+    \constd{POSIX\_MADV\_RANDOM}  & identico a \const{MADV\_RANDOM}.\\
+    \constd{POSIX\_MADV\_SEQUENTIAL}& identico a \const{MADV\_SEQUENTIAL}.\\
+    \constd{POSIX\_MADV\_WILLNEED}& identico a \const{MADV\_WILLNEED}.\\
      \hline
   \end{tabular}
   \caption{Valori dell'argomento \param{advice} di \func{posix\_madvise}.}
@@ -2050,13 +4904,15 @@ processi che vi facciano riferimento, non viene alterata. A parte la presenza
 dell'ulteriore argomento il comportamento delle funzioni è identico alle
 precedenti \func{readv} e \func{writev}. 
 
-Con l'uso di queste funzioni si possono evitare eventuali
-\itindex{race~condition} \textit{race condition} quando si deve eseguire la
-una operazione di lettura e scrittura vettorizzata a partire da una certa
-posizione su un file, mentre al contempo si possono avere in concorrenza
-processi che utilizzano lo stesso file descriptor (si ricordi quanto visto in
-sez.~\ref{sec:file_adv_func}) con delle chiamate a \func{lseek}.
+Con l'uso di queste funzioni si possono evitare eventuali \textit{race
+  condition} quando si deve eseguire la una operazione di lettura e scrittura
+vettorizzata a partire da una certa posizione su un file, mentre al contempo
+si possono avere in concorrenza processi che utilizzano lo stesso file
+descriptor (si ricordi quanto visto in sez.~\ref{sec:file_adv_func}) con delle
+chiamate a \func{lseek}.
 
+% TODO trattare preadv2() e pwritev2(), introdotte con il kernel 4.6, vedi
+% http://lwn.net/Articles/670231/ ed il flag RWF_HIPRI
 
 
 \subsection{L'I/O diretto fra file descriptor: \func{sendfile} e
@@ -2296,55 +5152,55 @@ descrizioni complete di tutti i valori possibili anche quando, come per
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \const{SPLICE\_F\_MOVE}    & Suggerisce al kernel di spostare le pagine
-                                 di memoria contenenti i dati invece di
-                                 copiarle: per una maggiore efficienza
-                                 \func{splice} usa quando possibile i
-                                 meccanismi della memoria virtuale per
-                                 eseguire i trasferimenti di dati. In maniera
-                                 analoga a \func{mmap}), qualora le pagine non
-                                 possano essere spostate dalla \textit{pipe} o
-                                 il buffer non corrisponda a pagine intere
-                                 esse saranno comunque copiate. Viene usato
-                                 soltanto da \func{splice}.\\ 
-    \const{SPLICE\_F\_NONBLOCK}& Richiede di operare in modalità non
-                                 bloccante; questo flag influisce solo sulle
-                                 operazioni che riguardano l'I/O da e verso la
-                                 \textit{pipe}. Nel caso di \func{splice}
-                                 questo significa che la funzione potrà
-                                 comunque bloccarsi nell'accesso agli altri
-                                 file descriptor (a meno che anch'essi non
-                                 siano stati aperti in modalità non
-                                 bloccante).\\
-    \const{SPLICE\_F\_MORE}    & Indica al kernel che ci sarà l'invio di
-                                 ulteriori dati in una \func{splice}
-                                 successiva, questo è un suggerimento utile
-                                 che viene usato quando \param{fd\_out} è un
-                                 socket. Questa opzione consente di utilizzare
-                                 delle opzioni di gestione dei socket che
-                                 permettono di ottimizzare le trasmissioni via
-                                 rete (si veda la descrizione di
-                                 \const{TCP\_CORK} in
-                                 sez.~\ref{sec:sock_tcp_udp_options} e quella
-                                 di \const{MSG\_MORE} in
-                                 sez.~\ref{sec:net_sendmsg}).  Attualmente
-                                 viene usato solo da \func{splice}, potrà essere
-                                 implementato in futuro anche per
-                                 \func{vmsplice} e \func{tee}.\\
-    \const{SPLICE\_F\_GIFT}    & Le pagine di memoria utente sono
-                                 ``\textsl{donate}'' al kernel; questo
-                                 significa che la cache delle pagine e i dati
-                                 su disco potranno differire, e che
-                                 l'applicazione non potrà modificare
-                                 quest'area di memoria. 
-                                 Se impostato una seguente \func{splice} che
-                                 usa \const{SPLICE\_F\_MOVE} potrà spostare le 
-                                 pagine con successo, altrimenti esse dovranno
-                                 essere copiate; per usare questa opzione i
-                                 dati dovranno essere opportunamente allineati
-                                 in posizione ed in dimensione alle pagine di
-                                 memoria. Viene usato soltanto da
-                                 \func{vmsplice}.\\
+    \constd{SPLICE\_F\_MOVE} & Suggerisce al kernel di spostare le pagine
+                               di memoria contenenti i dati invece di
+                               copiarle: per una maggiore efficienza
+                               \func{splice} usa quando possibile i
+                               meccanismi della memoria virtuale per
+                               eseguire i trasferimenti di dati. In maniera
+                               analoga a \func{mmap}), qualora le pagine non
+                               possano essere spostate dalla \textit{pipe} o
+                               il buffer non corrisponda a pagine intere
+                               esse saranno comunque copiate. Viene usato
+                               soltanto da \func{splice}.\\ 
+    \constd{SPLICE\_F\_NONBLOCK}& Richiede di operare in modalità non
+                                  bloccante; questo flag influisce solo sulle
+                                  operazioni che riguardano l'I/O da e verso la
+                                  \textit{pipe}. Nel caso di \func{splice}
+                                  questo significa che la funzione potrà
+                                  comunque bloccarsi nell'accesso agli altri
+                                  file descriptor (a meno che anch'essi non
+                                  siano stati aperti in modalità non
+                                  bloccante).\\
+    \constd{SPLICE\_F\_MORE} & Indica al kernel che ci sarà l'invio di
+                               ulteriori dati in una \func{splice}
+                               successiva, questo è un suggerimento utile
+                               che viene usato quando \param{fd\_out} è un
+                               socket. Questa opzione consente di utilizzare
+                               delle opzioni di gestione dei socket che
+                               permettono di ottimizzare le trasmissioni via
+                               rete (si veda la descrizione di
+                               \const{TCP\_CORK} in
+                               sez.~\ref{sec:sock_tcp_udp_options} e quella
+                               di \const{MSG\_MORE} in
+                               sez.~\ref{sec:net_sendmsg}).  Attualmente
+                               viene usato solo da \func{splice}, potrà essere
+                               implementato in futuro anche per
+                               \func{vmsplice} e \func{tee}.\\
+    \constd{SPLICE\_F\_GIFT} & Le pagine di memoria utente sono
+                               ``\textsl{donate}'' al kernel; questo
+                               significa che la cache delle pagine e i dati
+                               su disco potranno differire, e che
+                               l'applicazione non potrà modificare
+                               quest'area di memoria. 
+                               Se impostato una seguente \func{splice} che
+                               usa \const{SPLICE\_F\_MOVE} potrà spostare le 
+                               pagine con successo, altrimenti esse dovranno
+                               essere copiate; per usare questa opzione i
+                               dati dovranno essere opportunamente allineati
+                               in posizione ed in dimensione alle pagine di
+                               memoria. Viene usato soltanto da
+                               \func{vmsplice}.\\
     \hline
   \end{tabular}
   \caption{Le costanti che identificano i bit della maschera binaria
@@ -2598,6 +5454,9 @@ copiati i puntatori.
 % TODO?? dal 2.6.25 splice ha ottenuto il supporto per la ricezione su rete
 
 
+% TODO trattare qui copy_file_range (vedi http://lwn.net/Articles/659523/),
+% introdotta nel kernel 4.5
+
 \subsection{Gestione avanzata dell'accesso ai dati dei file}
 \label{sec:file_fadvise}
 
@@ -2727,19 +5586,19 @@ che utilizza semplicemente l'informazione.
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \const{POSIX\_FADV\_NORMAL}  & Non ci sono avvisi specifici da fare
+    \constd{POSIX\_FADV\_NORMAL}  & Non ci sono avvisi specifici da fare
                                    riguardo le modalità di accesso, il
                                    comportamento sarà identico a quello che si
                                    avrebbe senza nessun avviso.\\ 
-    \const{POSIX\_FADV\_SEQUENTIAL}& L'applicazione si aspetta di accedere di
+    \constd{POSIX\_FADV\_SEQUENTIAL}& L'applicazione si aspetta di accedere di
                                    accedere ai dati specificati in maniera
                                    sequenziale, a partire dalle posizioni più
                                    basse.\\ 
-    \const{POSIX\_FADV\_RANDOM}  & I dati saranno letti in maniera
+    \constd{POSIX\_FADV\_RANDOM}  & I dati saranno letti in maniera
                                    completamente causale.\\
-    \const{POSIX\_FADV\_NOREUSE} & I dati saranno acceduti una sola volta.\\ 
-    \const{POSIX\_FADV\_WILLNEED}& I dati saranno acceduti a breve.\\ 
-    \const{POSIX\_FADV\_DONTNEED}& I dati non saranno acceduti a breve.\\ 
+    \constd{POSIX\_FADV\_NOREUSE} & I dati saranno acceduti una sola volta.\\ 
+    \constd{POSIX\_FADV\_WILLNEED}& I dati saranno acceduti a breve.\\ 
+    \constd{POSIX\_FADV\_DONTNEED}& I dati non saranno acceduti a breve.\\ 
     \hline
   \end{tabular}
   \caption{Valori delle costanti usabili per l'argomento \param{advice} di
@@ -2893,9 +5752,9 @@ quello di \func{posix\_fallocate} e si può considerare \func{fallocate} come
 l'implementazione ottimale della stessa a livello di kernel.
 
 Inizialmente l'unico altro valore possibile per \param{mode} era
-\const{FALLOC\_FL\_KEEP\_SIZE} che richiede che la dimensione del file (quella
-ottenuta nel campo \var{st\_size} di una struttura \struct{stat} dopo una
-chiamata a \texttt{fstat}) non venga modificata anche quando la somma
+\const{FALLOC\_FL\_KEEP\_SIZE} che richiede che la dimensione del file
+(quella ottenuta nel campo \var{st\_size} di una struttura \struct{stat} dopo
+una chiamata a \texttt{fstat}) non venga modificata anche quando la somma
 di \param{offset} e \param{len} eccede la dimensione corrente, che serve
 quando si deve comunque preallocare dello spazio per scritture in append. In
 seguito sono stati introdotti altri valori, riassunti in
@@ -2910,16 +5769,16 @@ allocazione dello spazio disco dei file.
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
-    \const{FALLOC\_FL\_INSERT}     & .\\
-    \const{FALLOC\_FL\_COLLAPSE\_RANGE}& .\\ 
-    \const{FALLOC\_FL\_KEEP\_SIZE} & Mantiene invariata la dimensione del
+    \constd{FALLOC\_FL\_INSERT}     & .\\
+    \constd{FALLOC\_FL\_COLLAPSE\_RANGE}& .\\ 
+    \constd{FALLOC\_FL\_KEEP\_SIZE} & Mantiene invariata la dimensione del
                                      file, pur allocando lo spazio disco anche
                                      oltre la dimensione corrente del file.\\
-    \const{FALLOC\_FL\_PUNCH\_HOLE}& Crea un \textsl{buco} nel file (vedi
+    \constd{FALLOC\_FL\_PUNCH\_HOLE}& Crea un \textsl{buco} nel file (vedi
                                      sez.~\ref{sec:file_lseek}) rendendolo una
                                      \textit{sparse file} (dal kernel
                                      2.6.38).\\  
-    \const{FALLOC\_FL\_ZERO\_RANGE}& .\\ 
+    \constd{FALLOC\_FL\_ZERO\_RANGE}& .\\ 
     \hline
   \end{tabular}
   \caption{Valori delle costanti usabili per l'argomento \param{mode} di