Indicizzati file sotto /proc, ed ulteriore materiale su ''inotify''.
[gapil.git] / fileadv.tex
index de7ae5d50ae1aa153e836965c4ffd8691b579a3a..662d8f8afaae9c9f03d0890d4eec82f915cec2f7 100644 (file)
@@ -1,6 +1,6 @@
 %% fileadv.tex
 %%
-%% Copyright (C) 2000-2004 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2007 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",
@@ -36,14 +36,13 @@ I/O.
 \label{sec:file_noblocking}
 
 Abbiamo visto in sez.~\ref{sec:sig_gen_beha}, affrontando la suddivisione fra
-\textit{fast} e \textit{slow} system call,\index{system call lente} che in
+\textit{fast} e \textit{slow} system call,\index{system~call~lente} che in
 certi casi le funzioni di I/O possono bloccarsi indefinitamente.\footnote{si
-  ricordi però che questo può accadere solo per le pipe, i
-  socket\index{socket} ed alcuni file di dispositivo\index{file!di
-    dispositivo}; sui file normali le funzioni di lettura e scrittura
-  ritornano sempre subito.}  Ad esempio le operazioni di lettura possono
-bloccarsi quando non ci sono dati disponibili sul descrittore su cui si sta
-operando.
+  ricordi però che questo può accadere solo per le pipe, i socket ed alcuni
+  file di dispositivo\index{file!di~dispositivo}; sui file normali le funzioni
+  di lettura e scrittura ritornano sempre subito.}  Ad esempio le operazioni
+di lettura possono bloccarsi quando non ci sono dati disponibili sul
+descrittore su cui si sta operando.
 
 Questo comportamento causa uno dei problemi più comuni che ci si trova ad
 affrontare nelle operazioni di I/O, che si verifica quando si deve operare con
@@ -51,12 +50,12 @@ pi
 possibile prevedere quando questo può avvenire (il caso più classico è quello
 di un server in attesa di dati in ingresso da vari client). Quello che può
 accadere è di restare bloccati nell'eseguire una operazione su un file
-descriptor che non è ``\textsl{pronto}'', quando ce ne potrebbe essere
-un'altro disponibile. Questo comporta nel migliore dei casi una operazione
+descriptor che non è ``\textsl{pronto}'', quando ce ne potrebbe essere un
+altro disponibile. Questo comporta nel migliore dei casi una operazione
 ritardata inutilmente nell'attesa del completamento di quella bloccata, mentre
 nel peggiore dei casi (quando la conclusione della operazione bloccata dipende
 da quanto si otterrebbe dal file descriptor ``\textsl{disponibile}'') si
-potrebbe addirittura arrivare ad un \textit{deadlock}\index{deadlock}.
+potrebbe addirittura arrivare ad un \itindex{deadlock} \textit{deadlock}.
 
 Abbiamo già accennato in sez.~\ref{sec:file_open} che è possibile prevenire
 questo tipo di comportamento delle funzioni di I/O aprendo un file in
@@ -66,23 +65,24 @@ 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}\index{polling}, è
+Ovviamente questa tecnica, detta \itindex{polling} \textit{polling}, è
 estremamente inefficiente: si tiene costantemente impiegata la CPU solo per
 eseguire in continuazione delle system call che nella gran parte dei casi
 falliranno.
 
 Per superare questo problema è stato introdotto il concetto di \textit{I/O
-  multiplexing}, una nuova modalità di operazioni che consenta di tenere sotto
+  multiplexing}, una nuova modalità di operazioni che consente di tenere sotto
 controllo più file descriptor in contemporanea, permettendo di bloccare un
 processo quando le operazioni volute non sono possibili, e di riprenderne
-l'esecuzione una volta che almeno una di quelle richieste sia disponibile, in
+l'esecuzione una volta che almeno una di quelle richieste sia effettuabile, in
 modo da poterla eseguire con la sicurezza di non restare bloccati.
 
 Dato che, come abbiamo già accennato, per i normali file su disco non si ha
 mai un accesso bloccante, l'uso più comune delle funzioni che esamineremo nei
 prossimi paragrafi è per i server di rete, in cui esse vengono utilizzate per
 tenere sotto controllo dei socket; pertanto ritorneremo su di esse con
-ulteriori dettagli e qualche esempio in sez.~\ref{sec:TCP_sock_multiplexing}.
+ulteriori dettagli e qualche esempio di utilizzo concreto in
+sez.~\ref{sec:TCP_sock_multiplexing}.
 
 
 \subsection{Le funzioni \func{select} e \func{pselect}}
@@ -91,13 +91,13 @@ ulteriori dettagli e qualche esempio in sez.~\ref{sec:TCP_sock_multiplexing}.
 Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
   multiplexing} è stato BSD,\footnote{la funzione \func{select} è apparsa in
   BSD4.2 e standardizzata in BSD4.4, ma è stata portata su tutti i sistemi che
-  supportano i \textit{socket}\index{socket}, compreso le varianti di System
-  V.}  con la funzione \funcd{select}, il cui prototipo è:
+  supportano i socket, compreso le varianti di System V.}  con la funzione
+\funcd{select}, il cui prototipo è:
 \begin{functions}
   \headdecl{sys/time.h}
   \headdecl{sys/types.h}
   \headdecl{unistd.h}
-  \funcdecl{int select(int n, fd\_set *readfds, fd\_set *writefds, fd\_set
+  \funcdecl{int select(int ndfs, fd\_set *readfds, fd\_set *writefds, fd\_set
     *exceptfds, struct timeval *timeout)}
   
   Attende che uno dei file descriptor degli insiemi specificati diventi
@@ -110,8 +110,8 @@ Il primo kernel unix-like ad introdurre una interfaccia per l'\textit{I/O
   \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
     degli insiemi.
   \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
-  \item[\errcode{EINVAL}] Si è specificato per \param{n} un valore negativo o
-    un valore non valido per \param{timeout}.
+  \item[\errcode{EINVAL}] Si è specificato per \param{ndfs} un valore negativo
+    un valore non valido per \param{timeout}.
   \end{errlist}
   ed inoltre \errval{ENOMEM}.
 }
@@ -123,28 +123,29 @@ degli insiemi specificati (\param{readfds}, \param{writefds} e
 \param{exceptfds}), non diventa attivo, per un tempo massimo specificato da
 \param{timeout}.
 
+\itindbeg{file~descriptor~set} 
+
 Per specificare quali file descriptor si intende \textsl{selezionare}, la
 funzione usa un particolare oggetto, il \textit{file descriptor set},
 identificato dal tipo \type{fd\_set}, che serve ad identificare un insieme di
-file descriptor, in maniera analoga a come un 
-\index{\textit{signal set}}\textit{signal set} (vedi
-sez.~\ref{sec:sig_sigset}) identifica un insieme di segnali. Per la
-manipolazione di questi \textit{file descriptor set} si possono usare delle
-opportune macro di preprocessore:
+file descriptor, in maniera analoga a come un \itindex{signal~set}
+\textit{signal set} (vedi sez.~\ref{sec:sig_sigset}) identifica un insieme di
+segnali. Per la manipolazione di questi \textit{file descriptor set} si
+possono usare delle opportune macro di preprocessore:
 \begin{functions}
   \headdecl{sys/time.h}
   \headdecl{sys/types.h}
   \headdecl{unistd.h}
-  \funcdecl{FD\_ZERO(fd\_set *set)}
+  \funcdecl{void \macro{FD\_ZERO}(fd\_set *set)}
   Inizializza l'insieme (vuoto).
 
-  \funcdecl{FD\_SET(int fd, fd\_set *set)}
+  \funcdecl{void \macro{FD\_SET}(int fd, fd\_set *set)}
   Inserisce il file descriptor \param{fd} nell'insieme.
 
-  \funcdecl{FD\_CLR(int fd, fd\_set *set)}
-  Rimuove il file descriptor \param{fd} nell'insieme.
+  \funcdecl{void \macro{FD\_CLR}(int fd, fd\_set *set)}
+  Rimuove il file descriptor \param{fd} dall'insieme.
   
-  \funcdecl{FD\_ISSET(int fd, fd\_set *set)}
+  \funcdecl{int \macro{FD\_ISSET}(int fd, fd\_set *set)}
   Controlla se il file descriptor \param{fd} è nell'insieme.
 \end{functions}
 
@@ -158,45 +159,62 @@ massimo, esso indica le dimensioni massime dei numeri usati nei \textit{file
   1003.1-2001, è definito in \file{sys/select.h}, ed è pari a 1024.} Si tenga
 presente che i \textit{file descriptor set} devono sempre essere inizializzati
 con \macro{FD\_ZERO}; passare a \func{select} un valore non inizializzato può
-dar luogo a comportamenti non prevedibili.
+dar luogo a comportamenti non prevedibili; allo stesso modo usare
+\macro{FD\_SET} o \macro{FD\_CLR} con un file descriptor il cui valore eccede
+\const{FD\_SETSIZE} può dare luogo ad un comportamento indefinito.
 
 La funzione richiede di specificare tre insiemi distinti di file descriptor;
 il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
 effettuare una lettura,\footnote{per essere precisi la funzione ritornerà in
   tutti i casi in cui la successiva esecuzione di \func{read} risulti non
-  bloccante, quindi anche in caso di \textit{end-of-file}.} il secondo,
+  bloccante, quindi anche in caso di \textit{end-of-file}; inoltre con Linux
+  possono verificarsi casi particolari, ad esempio quando arrivano dati su un
+  socket dalla rete che poi risultano corrotti e vengono scartati, può
+  accadere che \func{select} riporti il relativo file descriptor come
+  leggibile, ma una successiva \func{read} si blocchi.} il secondo,
 \param{writefds}, per verificare la possibilità effettuare una scrittura ed il
-terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i
-messaggi urgenti su un \textit{socket}\index{socket}, vedi
+terzo, \param{exceptfds}, per verificare l'esistenza di eccezioni (come i dati
+urgenti \itindex{out-of-band} su un socket, vedi
 sez.~\ref{sec:TCP_urgent_data}).
 
 Dato che in genere non si tengono mai sotto controllo fino a
 \const{FD\_SETSIZE} file contemporaneamente la funzione richiede di
-specificare qual'è il numero massimo dei file descriptor indicati nei tre
+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{n}, che
-deve corrispondere al valore massimo aumentato di uno.\footnote{i file
-  descriptor infatti sono contati a partire da zero, ed il valore indica il
-  numero di quelli da tenere sotto controllo; dimenticarsi di aumentare di uno
-  il valore di \param{n} è un errore comune.}  Infine l'argomento
-\param{timeout}, specifica un tempo massimo di attesa prima che la funzione
-ritorni; se impostato a \val{NULL} la funzione attende indefinitamente. Si può
-specificare anche un tempo nullo (cioè una struttura \struct{timeval} con i
-campi impostati a zero), qualora si voglia semplicemente controllare lo stato
-corrente dei file descriptor.
+necessaria. Questo limite viene indicato tramite l'argomento \param{ndfs}, che
+deve corrispondere al valore massimo aumentato di uno.\footnote{si ricordi che
+  i file descriptor sono numerati progressivamente a partire da zero, ed il
+  valore indica il numero più alto fra quelli da tenere sotto controllo;
+  dimenticarsi di aumentare di uno il valore di \param{ndfs} è un errore
+  comune.}  Infine l'argomento \param{timeout} specifica un tempo massimo di
+attesa prima che la funzione ritorni; se impostato a \val{NULL} la funzione
+attende indefinitamente. Si può specificare anche un tempo nullo (cioè una
+struttura \struct{timeval} con i campi impostati a zero), qualora si voglia
+semplicemente controllare lo stato corrente dei file descriptor.
 
 La funzione restituisce il numero di file descriptor pronti,\footnote{questo è
   il comportamento previsto dallo standard, ma la standardizzazione della
   funzione è recente, ed esistono ancora alcune versioni di Unix che non si
   comportano in questo modo.}  e ciascun insieme viene sovrascritto per
 indicare quali sono i file descriptor pronti per le operazioni ad esso
-relative, in modo da poterli controllare con \const{FD\_ISSET}.  Se invece si
+relative, in modo da poterli controllare con \macro{FD\_ISSET}.  Se invece si
 ha un timeout viene restituito un valore nullo e gli insiemi non vengono
 modificati.  In caso di errore la funzione restituisce -1, ed i valori dei tre
 insiemi sono indefiniti e non si può fare nessun affidamento sul loro
 contenuto.
 
+\itindend{file~descriptor~set}
+
+Una volta ritornata la funzione si potrà controllare quali sono i file
+descriptor pronti ed operare su di essi, si tenga presente però che si tratta
+solo di un suggerimento, esistono infatti condizioni\footnote{ad esempio
+  quando su un socket arrivano dei dati che poi vengono scartati perché
+  corrotti.} in cui \func{select} può riportare in maniera spuria che un file
+descriptor è pronto in lettura, quando una successiva lettura si bloccherebbe.
+Per questo quando si usa \textit{I/O multiplexing} è sempre raccomandato l'uso
+delle funzioni di lettura e scrittura in modalità non bloccante.
+
 In Linux \func{select} modifica anche il valore di \param{timeout},
 impostandolo al tempo restante in caso di interruzione prematura; questo è
 utile quando la funzione viene interrotta da un segnale, in tal caso infatti
@@ -211,16 +229,16 @@ rimanente.\footnote{questo pu
 
 Uno dei problemi che si presentano con l'uso di \func{select} è che il suo
 comportamento dipende dal valore del file descriptor che si vuole tenere sotto
-controllo.  Infatti il kernel riceve con \param{n} un valore massimo per tale
-valore, e per capire quali sono i file descriptor da tenere sotto controllo
-dovrà effettuare una scansione su tutto l'intervallo, che può anche essere
-anche molto ampio anche se i file descriptor sono solo poche unità; tutto ciò
+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 arbitario si viene a creare una dipendenza del tutto artificiale dalle
+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. 
 
@@ -252,8 +270,8 @@ precedenti, ed inoltre aggiunge a \func{select} una nuova funzione
   \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
     degli insiemi.
   \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
-  \item[\errcode{EINVAL}] Si è specificato per \param{n} un valore negativo o
-    un valore non valido per \param{timeout}.
+  \item[\errcode{EINVAL}] Si è specificato per \param{ndfs} un valore negativo
+    un valore non valido per \param{timeout}.
   \end{errlist}
   ed inoltre \errval{ENOMEM}.}
 \end{prototype}
@@ -261,55 +279,59 @@ precedenti, ed inoltre aggiunge a \func{select} una nuova funzione
 La funzione è sostanzialmente identica a \func{select}, solo che usa una
 struttura \struct{timespec} (vedi fig.~\ref{fig:sys_timeval_struct}) per
 indicare con maggiore precisione il timeout e non ne aggiorna il valore in
-caso di interruzione. Inoltre prende un argomento aggiuntivo \param{sigmask}
-che è il puntatore ad una maschera di segnali (si veda
-sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa
+caso di interruzione.\footnote{in realtà la system call di Linux aggiorna il
+  valore al tempo rimanente, ma la funzione fornita dalle \acr{glibc} modifica
+  questo comportamento passando alla system call una variabile locale, in modo
+  da mantenere l'aderenza allo standard POSIX che richiede che il valore di
+  \param{timeout} non sia modificato.} Inoltre prende un argomento aggiuntivo
+\param{sigmask} che è il puntatore ad una maschera di segnali (si veda
+sez.~\ref{sec:sig_sigmask}).  La maschera corrente viene sostituita da questa
 immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della
 funzione.
 
 L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
-race condition\index{race condition} quando ci si deve porre in attesa sia di
-un segnale che di dati. La tecnica classica è quella di utilizzare il gestore
-per impostare una variabile globale e controllare questa nel corpo principale
-del programma; abbiamo visto in sez.~\ref{sec:sig_example} come questo lasci
-spazio a possibili race condition, per cui diventa essenziale utilizzare
-\func{sigprocmask} per disabilitare la ricezione del segnale prima di eseguire
-il controllo e riabilitarlo dopo l'esecuzione delle relative operazioni, onde
-evitare l'arrivo di un segnale immediatamente dopo il controllo, che andrebbe
-perso.
+\textit{race condition} \itindex{race~condition} quando ci si deve porre in
+attesa sia di un segnale che di dati. La tecnica classica è quella di
+utilizzare il gestore per impostare una variabile globale e controllare questa
+nel corpo principale del programma; abbiamo visto in
+sez.~\ref{sec:sig_example} come questo lasci spazio a possibili race
+condition, per cui diventa essenziale utilizzare \func{sigprocmask} per
+disabilitare la ricezione del segnale prima di eseguire il controllo e
+riabilitarlo dopo l'esecuzione delle relative operazioni, onde evitare
+l'arrivo di un segnale immediatamente dopo il controllo, che andrebbe perso.
 
 Nel nostro caso il problema si pone quando oltre al segnale si devono tenere
 sotto controllo anche dei file descriptor con \func{select}, in questo caso si
 può fare conto sul fatto che all'arrivo di un segnale essa verrebbe interrotta
 e si potrebbero eseguire di conseguenza le operazioni relative al segnale e
 alla gestione dati con un ciclo del tipo:
-\includecodesnip{listati/select_race.c} qui però emerge una race
-condition,\index{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.
+\includecodesnip{listati/select_race.c} 
+qui però emerge una \itindex{race~condition} \textit{race condition}, perché
+se il segnale arriva prima della chiamata a \func{select}, questa non verrà
+interrotta, e la ricezione del segnale non sarà rilevata.
 
 Per questo è stata introdotta \func{pselect} che attraverso l'argomento
 \param{sigmask} permette di riabilitare la ricezione il segnale
-contestualmente all'esecuzione della funzione,\footnote{in Linux però non è
-  presente la relativa system call, e la funzione è implementata nelle
-  \acr{glibc} attraverso \func{select} (vedi \texttt{man select\_tut}) per cui
-  la possibilità di race condition permane; esiste però una soluzione,
-  chiamata \index{\textit{self-pipe trick}}\textit{self-pipe trick}, che
-  consiste nell'aprire una pipe (vedi sez.~\ref{sec:ipc_pipes}) ed usare
-  \func{select} sul capo in lettura della stessa, e indicare l'arrivo di un
-  segnale scrivendo sul capo in scrittura all'interno del manipolatore; in
-  questo modo anche se il segnale va perso prima della chiamata di
-  \func{select} questa lo riconoscerà comunque dalla presenza di dati sulla
-  pipe.} ribloccandolo non appena essa ritorna, così che il precedente codice
-potrebbe essere riscritto nel seguente modo:
-\includecodesnip{listati/pselect_norace.c} in questo caso utilizzando
-\var{oldmask} durante l'esecuzione di \func{pselect} la ricezione del segnale
-sarà abilitata, ed in caso di interruzione si potranno eseguire le relative
-operazioni.
-
-
-
-\subsection{La funzione \func{poll}}
+contestualmente all'esecuzione della funzione,\footnote{in Linux però, fino al
+  kernel 2.6.16, non era presente la relativa system call, e la funzione era
+  implementata nelle \acr{glibc} attraverso \func{select} (vedi \texttt{man
+    select\_tut}) per cui la possibilità di \itindex{race~condition}
+  \textit{race condition} permaneva; in tale situazione si può ricorrere ad una
+  soluzione alternativa, chiamata \itindex{self-pipe trick} \textit{self-pipe
+    trick}, che consiste nell'aprire una pipe (vedi sez.~\ref{sec:ipc_pipes})
+  ed usare \func{select} sul capo in lettura della stessa; si può indicare
+  l'arrivo di un segnale scrivendo sul capo in scrittura all'interno del
+  gestore dello stesso; in questo modo anche se il segnale va perso prima
+  della chiamata di \func{select} questa lo riconoscerà comunque dalla
+  presenza di dati sulla pipe.} ribloccandolo non appena essa ritorna, così
+che il precedente codice potrebbe essere riscritto nel seguente modo:
+\includecodesnip{listati/pselect_norace.c} 
+in questo caso utilizzando \var{oldmask} durante l'esecuzione di
+\func{pselect} la ricezione del segnale sarà abilitata, ed in caso di
+interruzione si potranno eseguire le relative operazioni.
+
+
+\subsection{Le funzioni \func{poll} e \func{ppoll}}
 \label{sec:file_poll}
 
 Nello sviluppo di System V, invece di utilizzare l'interfaccia di
@@ -346,17 +368,6 @@ indica un'attesa indefinita, mentre un valore nullo comporta il ritorno
 immediato (e può essere utilizzato per impiegare \func{poll} in modalità
 \textsl{non-bloccante}).
 
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \includestruct{listati/pollfd.h}
-  \end{minipage} 
-  \normalsize 
-  \caption{La struttura \structd{pollfd}, utilizzata per specificare le
-    modalità di controllo di un file descriptor alla funzione \func{poll}.}
-  \label{fig:file_pollfd}
-\end{figure}
-
 Per ciascun file da controllare deve essere inizializzata una struttura
 \struct{pollfd} nel vettore indicato dall'argomento \param{ufds}.  La
 struttura, la cui definizione è riportata in fig.~\ref{fig:file_pollfd},
@@ -370,6 +381,17 @@ tutto indipendenti da quelli in uscita (che vengono restituiti in
 \var{revents}) non è necessario reinizializzare tutte le volte il valore delle
 strutture \struct{pollfd} a meno di non voler cambiare qualche condizione.
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/pollfd.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{pollfd}, utilizzata per specificare le
+    modalità di controllo di un file descriptor alla funzione \func{poll}.}
+  \label{fig:file_pollfd}
+\end{figure}
+
 Le costanti che definiscono i valori relativi ai bit usati nelle maschere
 binarie dei campi \var{events} e \var{revents} sono riportati in
 tab.~\ref{tab:file_pollfd_flags}, insieme al loro significato. Le si sono
@@ -388,12 +410,13 @@ nel campo \var{revents} per notificare delle condizioni di errore.
     \hline
     \const{POLLIN}    & È possibile la lettura.\\
     \const{POLLRDNORM}& Sono disponibili in lettura dati normali.\\ 
-    \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari. \\
-    \const{POLLPRI}   & È possibile la lettura di dati urgenti.\\
+    \const{POLLRDBAND}& Sono disponibili in lettura dati prioritari.\\
+    \const{POLLPRI}   & È possibile la lettura di \itindex{out-of-band} dati
+                        urgenti.\\ 
     \hline
     \const{POLLOUT}   & È possibile la scrittura immediata.\\
-    \const{POLLWRNORM}& È possibile la scrittura di dati normali.  \\ 
-    \const{POLLWRBAND}& È possibile la scrittura di dati prioritari. \\
+    \const{POLLWRNORM}& È possibile la scrittura di dati normali.\\ 
+    \const{POLLWRBAND}& È possibile la scrittura di dati prioritari.\\
     \hline
     \const{POLLERR}   & C'è una condizione di errore.\\
     \const{POLLHUP}   & Si è verificato un hung-up.\\
@@ -414,15 +437,15 @@ compatibilit
   delle librerie standard del C.} è da questi che derivano i nomi di alcune
 costanti, in quanto per essi sono definite tre classi di dati:
 \textsl{normali}, \textit{prioritari} ed \textit{urgenti}.  In Linux la
-distinzione ha senso solo per i dati \textit{out-of-band} dei socket (vedi
-sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll} reagisce
-alle varie condizioni dei socket torneremo in sez.~\ref{sec:TCP_serv_poll},
-dove vedremo anche un esempio del suo utilizzo. Si tenga conto comunque che le
-costanti relative ai diversi tipi di dati (come \macro{POLLRDNORM} e
-\macro{POLLRDBAND}) sono utilizzabili soltanto qualora si sia definita la
-macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di farlo sempre in
-  testa al file, definirla soltanto prima di includere \file{sys/poll.h} non è
-  sufficiente.}
+distinzione ha senso solo per i dati urgenti \itindex{out-of-band} dei socket
+(vedi sez.~\ref{sec:TCP_urgent_data}), ma su questo e su come \func{poll}
+reagisce alle varie condizioni dei socket torneremo in
+sez.~\ref{sec:TCP_serv_poll}, dove vedremo anche un esempio del suo utilizzo.
+Si tenga conto comunque che le costanti relative ai diversi tipi di dati (come
+\const{POLLRDNORM} e \const{POLLRDBAND}) sono utilizzabili soltanto qualora si
+sia definita la macro \macro{\_XOPEN\_SOURCE}.\footnote{e ci si ricordi di
+  farlo sempre in testa al file, definirla soltanto prima di includere
+  \file{sys/poll.h} non è sufficiente.}
 
 In caso di successo funzione ritorna restituendo il numero di file (un valore
 positivo) per i quali si è verificata una delle condizioni di attesa richieste
@@ -432,12 +455,444 @@ valore nullo indica che si 
 indica un errore nella chiamata, il cui codice viene riportato al solito
 tramite \var{errno}.
 
+L'uso di \func{poll} consente di superare alcuni dei problemi illustrati in
+precedenza per \func{select}; anzitutto, dato che in questo caso si usa un
+vettore di strutture \struct{pollfd} di dimensione arbitraria, non esiste il
+limite introdotto dalle dimensioni massime di un \itindex{file~descriptor~set}
+\textit{file descriptor set} e la dimensione dei dati passati al kernel
+dipende solo dal numero dei file descriptor che si vogliono controllare, non
+dal loro valore.\footnote{anche se usando dei bit un \textit{file descriptor
+    set} può essere più efficiente di un vettore di strutture \struct{pollfd},
+  qualora si debba osservare un solo file descriptor con un valore molto alto
+  ci si troverà ad utilizzare inutilmente un maggiore quantitativo di
+  memoria.} 
+
+Inoltre con \func{select} lo stesso \itindex{file~descriptor~set} \textit{file
+  descriptor set} è usato sia in ingresso che in uscita, e questo significa
+che tutte le volte che si vuole ripetere l'operazione occorre reinizializzarlo
+da capo. Questa operazione, che può essere molto onerosa se i file descriptor
+da tenere sotto osservazione sono molti, non è invece necessaria con
+\func{poll}.
+
+Abbiamo visto in sez.~\ref{sec:file_select} come lo standard POSIX preveda una
+variante di \func{select} che consente di gestire correttamente la ricezione
+dei segnali nell'attesa su un file descriptor.  Con l'introduzione di una
+implementazione reale di \func{pselect} nel kernel 2.6.16, è stata aggiunta
+anche una analoga funzione che svolga lo stesso ruolo per \func{poll}.
+
+In questo caso si tratta di una estensione che è specifica di Linux e non è
+prevista da nessuno standard; essa può essere utilizzata esclusivamente se si
+definisce la macro \macro{\_GNU\_SOURCE} ed ovviamente non deve essere usata
+se si ha a cuore la portabilità. La funzione è \funcd{ppoll}, ed il suo
+prototipo è:
+\begin{prototype}{sys/poll.h}
+  {int ppoll(struct pollfd *fds, nfds\_t nfds, const struct timespec *timeout,
+    const sigset\_t *sigmask)}
+  
+  La funzione attende un cambiamento di stato su un insieme di file
+  descriptor.
+  
+  \bodydesc{La funzione restituisce il numero di file descriptor con attività
+    in caso di successo, o 0 se c'è stato un timeout e -1 in caso di errore,
+    ed in quest'ultimo caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
+    degli insiemi.
+  \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+  \item[\errcode{EINVAL}] Il valore di \param{nfds} eccede il limite
+    \macro{RLIMIT\_NOFILE}.
+  \end{errlist}
+  ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
+\end{prototype}
+
+La funzione ha lo stesso comportamento di \func{poll}, solo che si può
+specificare, con l'argomento \param{sigmask}, il puntatore ad una maschera di
+segnali; questa sarà la maschera utilizzata per tutto il tempo che la funzione
+resterà in attesa, all'uscita viene ripristinata la maschera originale.  L'uso
+di questa funzione è cioè equivalente, come illustrato nella pagina di
+manuale, all'esecuzione atomica del seguente codice:
+\includecodesnip{listati/ppoll_means.c} 
+
+Eccetto per \param{timeout}, che come per \func{pselect} deve essere un
+puntatore ad una struttura \struct{timespec}, gli altri argomenti comuni con
+\func{poll} hanno lo stesso significato, e la funzione restituisce gli stessi
+risultati illustrati in precedenza.
+
+
+\subsection{L'interfaccia di \textit{epoll}}
+\label{sec:file_epoll}
+
+\itindbeg{epoll}
+
+Nonostante \func{poll} presenti alcuni vantaggi rispetto a \func{select},
+anche questa funzione non è molto efficiente quando deve essere utilizzata con
+un gran numero di file descriptor,\footnote{in casi del genere \func{select}
+  viene scartata a priori, perché può avvenire che il numero di file
+  descriptor ecceda le dimensioni massime di un \itindex{file~descriptor~set}
+  \textit{file descriptor set}.} in particolare nel caso in cui solo pochi di
+questi diventano attivi. Il problema in questo caso è che il tempo impiegato
+da \func{poll} a trasferire i dati da e verso il kernel è proporzionale al
+numero di file descriptor osservati, non a quelli che presentano attività.
+
+Quando ci sono decine di migliaia di file descriptor osservati e migliaia di
+eventi al secondo,\footnote{il caso classico è quello di un server web di un
+  sito con molti accessi.} l'uso di \func{poll} comporta la necessità di
+trasferire avanti ed indietro da user space a kernel space la lunga lista
+delle strutture \struct{pollfd} migliaia di volte al secondo. A questo poi si
+aggiunge il fatto che la maggior parte del tempo di esecuzione sarà impegnato
+ad eseguire una scansione su tutti i file descriptor tenuti sotto controllo
+per determinare quali di essi (in genere una piccola percentuale) sono
+diventati attivi. In una situazione come questa l'uso delle funzioni classiche
+dell'interfaccia dell'\textit{I/O multiplexing} viene a costituire un collo di
+bottiglia che degrada irrimediabilmente le prestazioni.
+
+Per risolvere questo tipo di situazioni sono state ideate delle interfacce
+specialistiche\footnote{come \texttt{/dev/poll} in Solaris, o \texttt{kqueue}
+  in BSD.} il cui scopo fondamentale è quello di restituire solamente le
+informazioni relative ai file descriptor osservati che presentano una
+attività, evitando così le problematiche appena illustrate. In genere queste
+prevedono che si registrino una sola volta i file descriptor da tenere sotto
+osservazione, e forniscono un meccanismo che notifica quali di questi
+presentano attività.
+
+Le modalità con cui avviene la notifica sono due, la prima è quella classica
+(quella usata da \func{poll} e \func{select}) che viene chiamata \textit{level
+  triggered}.\footnote{la nomenclatura è stata introdotta da Jonathan Lemon in
+  un articolo su \texttt{kqueue} al BSDCON 2000, e deriva da quella usata
+  nell'elettronica digitale.} In questa modalità vengono notificati i file
+descriptor che sono \textsl{pronti} per l'operazione richiesta, e questo
+avviene indipendentemente dalle operazioni che possono essere state fatte su
+di essi a partire dalla precedente notifica.  Per chiarire meglio il concetto
+ricorriamo ad un esempio: se su un file descriptor sono diventati disponibili
+in lettura 2000 byte ma dopo la notifica ne sono letti solo 1000 (ed è quindi
+possibile eseguire una ulteriore lettura dei restanti 1000), in modalità
+\textit{level triggered} questo sarà nuovamente notificato come
+\textsl{pronto}.
+
+La seconda modalità, è detta \textit{edge triggered}, e prevede che invece
+vengano notificati solo i file descriptor che hanno subito una transizione da
+\textsl{non pronti} a \textsl{pronti}. Questo significa che in modalità
+\textit{edge triggered} nel caso del precedente esempio il file descriptor
+diventato pronto da cui si sono letti solo 1000 byte non verrà nuovamente
+notificato come pronto, nonostante siano ancora disponibili in lettura 1000
+byte. Solo una volta che si saranno esauriti tutti i byte disponibili, e che
+il file descriptor sia tornato non essere pronto, si potrà ricevere una
+ulteriore notifica qualora ritornasse pronto.
+
+Nel caso di Linux al momento la sola interfaccia che fornisce questo tipo di
+servizio è \textit{epoll},\footnote{l'interfaccia è stata creata da Davide
+  Libenzi, ed è stata introdotta per la prima volta nel kernel 2.5.44, ma la
+  sua forma definitiva è stata raggiunta nel kernel 2.5.66.} anche se sono in
+discussione altre interfacce con le quali si potranno effettuare lo stesso
+tipo di operazioni;\footnote{al momento della stesura di queste note (Giugno
+  2007) un'altra interfaccia proposta è quella di \textit{kevent}, che
+  fornisce un sistema di notifica di eventi generico in grado di fornire le
+  stesse funzionalità di \textit{epoll}, esiste però una forte discussione
+  intorno a tutto ciò e niente di definito.}  \textit{epoll} è in grado di
+operare sia in modalità \textit{level triggered} che \textit{edge triggered}.
+
+La prima versione \textit{epoll} prevedeva l'apertura di uno speciale file di
+dispositivo, \texttt{/dev/epoll}, per ottenere un file descriptor da
+utilizzare con le funzioni dell'interfaccia,\footnote{il backporting
+  dell'interfaccia per il kernel 2.4, non ufficiale, utilizza sempre questo
+  file.} ma poi si è passati all'uso una apposita \textit{system call}.  Il
+primo passo per usare l'interfaccia di \textit{epoll} è pertanto quello di
+chiamare la funzione \funcd{epoll\_create}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+  {int epoll\_create(int size)}
+  
+  Apre un file descriptor per \textit{epoll}.
+  
+  \bodydesc{La funzione restituisce un file descriptor in caso di successo, o
+    $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EINVAL}] si è specificato un valore di \param{size} non
+    positivo.
+  \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{prototype}
+
+La funzione restituisce un file descriptor speciale,\footnote{esso non è
+  associato a nessun file su disco, inoltre a differenza dei normali file
+  descriptor non può essere inviato ad un altro processo attraverso un socket
+  locale (vedi sez.~\ref{sec:sock_fd_passing}).} detto anche \textit{epoll
+  descriptor}, che viene associato alla infrastruttura utilizzata dal kernel
+per gestire la notifica degli eventi; l'argomento \param{size} serve a dare
+l'indicazione del numero di file descriptor che si vorranno tenere sotto
+controllo, ma costituisce solo un suggerimento per semplificare l'allocazione
+di risorse sufficienti, non un valore massimo.
+
+Una volta ottenuto un file descriptor per \textit{epoll} il passo successivo è
+indicare quali file descriptor mettere sotto osservazione e quali operazioni
+controllare, per questo si deve usare la seconda funzione dell'interfaccia,
+\funcd{epoll\_ctl}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+  {int epoll\_ctl(int epfd, int op, int fd, struct epoll\_event *event)}
+  
+  Esegue le operazioni di controllo di \textit{epoll}.
+  
+  \bodydesc{La funzione restituisce $0$ in caso di successo o $-1$ in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] il file descriptor \param{epfd} o \param{fd} non sono
+    validi.
+  \item[\errcode{EEXIST}] l'operazione richiesta è \const{EPOLL\_CTL\_ADD} ma
+    \param{fd} è già stato inserito in \param{epfd}.
+  \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+    con \func{epoll\_create}, o \param{fd} è lo stesso \param{epfd} o
+    l'operazione richiesta con \param{op} non è supportata.
+  \item[\errcode{ENOENT}] l'operazione richiesta è \const{EPOLL\_CTL\_MOD} o
+    \const{EPOLL\_CTL\_DEL} ma \param{fd} non è inserito in \param{epfd}.
+  \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel gestire
+    l'operazione richiesta.
+  \item[\errcode{EPERM}] il file \param{fd} non supporta \textit{epoll}.
+  \end{errlist}
+}
+\end{prototype}
+
+Il comportamento della funzione viene controllato dal valore dall'argomento
+\param{op} che consente di specificare quale operazione deve essere eseguita.
+Le costanti che definiscono i valori utilizzabili per \param{op}
+sono riportate in tab.~\ref{tab:epoll_ctl_operation}, assieme al significato
+delle operazioni cui fanno riferimento.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{EPOLL\_CTL\_ADD}& Aggiunge un nuovo file descriptor da osservare
+                             \param{fd} alla lista dei file descriptor
+                             controllati tramite \param{epfd}, in
+                             \param{event} devono essere specificate le
+                             modalità di osservazione.\\
+    \const{EPOLL\_CTL\_MOD}& Modifica le modalità di osservazione del file
+                             descriptor \param{fd} secondo il contenuto di
+                             \param{event}.\\
+    \const{EPOLL\_CTL\_DEL}& Rimuove il file descriptor \param{fd} dalla lista
+                             dei file controllati tramite \param{epfd}.\\
+    \hline    
+  \end{tabular}
+  \caption{Valori dell'argomento \param{op} che consentono di scegliere quale
+    operazione di controllo effettuare con la funzione \func{epoll\_ctl}.} 
+  \label{tab:epoll_ctl_operation}
+\end{table}
+
+La funzione prende sempre come primo argomento un file descriptor di
+\textit{epoll}, \param{epfd}, che deve essere stato ottenuto in precedenza con
+una chiamata a \func{epoll\_create}. L'argomento \param{fd} indica invece il
+file descriptor che si vuole tenere sotto controllo, quest'ultimo può essere
+un qualunque file descriptor utilizzabile con \func{poll}, ed anche un altro
+file descriptor di \textit{epoll}, ma non lo stesso \param{epfd}.
+
+L'ultimo argomento, \param{event}, deve essere un puntatore ad una struttura
+di tipo \struct{epoll\_event}, ed ha significato solo con le operazioni
+\const{EPOLL\_CTL\_MOD} e \const{EPOLL\_CTL\_ADD}, per le quali serve ad
+indicare quale tipo di evento relativo ad \param{fd} si vuole che sia tenuto
+sotto controllo.  L'argomento viene ignorato con l'operazione
+\const{EPOLL\_CTL\_DEL}.\footnote{fino al kernel 2.6.9 era comunque richiesto
+  che questo fosse un puntatore valido, anche se poi veniva ignorato, a
+  partire dal 2.6.9 si può specificare anche anche un valore \texttt{NULL}.}
+
+
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/epoll_event.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{epoll\_event}, che consente di specificare
+    gli eventi associati ad un file descriptor controllato con
+    \textit{epoll}.}
+  \label{fig:epoll_event}
+\end{figure}
+
+La struttura \struct{epoll\_event} è l'analoga di \struct{pollfd} e come
+quest'ultima serve sia in ingresso (quando usata con \func{epoll\_ctl}) ad
+impostare quali eventi osservare, che in uscita (nei risultati ottenuti con
+\func{epoll\_wait}) per ricevere le notifiche degli eventi avvenuti.  La sua
+definizione è riportata in fig.~\ref{fig:epoll_event}. 
+
+Il primo campo, \var{events}, è una maschera binaria in cui ciascun bit
+corrisponde o ad un tipo di evento, o una modalità di notifica; detto campo
+deve essere specificato come OR aritmetico delle costanti riportate in
+tab.~\ref{tab:epoll_events}. Il secondo campo, \var{data}, serve ad indicare a
+quale file descriptor si intende fare riferimento, ed in astratto può
+contenere un valore qualsiasi che permetta di identificarlo, di norma comunque
+si usa come valore lo stesso \param{fd}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{EPOLLIN}     & Il file è pronto per le operazioni di lettura
+                          (analogo di \const{POLLIN}).\\
+    \const{EPOLLOUT}    & Il file è pronto per le operazioni di scrittura
+                          (analogo di \const{POLLOUT}).\\
+    \const{EPOLLRDHUP}  & l'altro capo di un socket di tipo
+                          \const{SOCK\_STREAM} (vedi sez.~\ref{sec:sock_type})
+                          ha chiuso la connessione o il capo in scrittura
+                          della stessa (vedi sez.~\ref{sec:TCP_shutdown}).\\
+    \const{EPOLLPRI}    & Ci sono \itindex{out-of-band} dati urgenti
+                          disponibili in lettura (analogo di
+                          \const{POLLPRI}); questa condizione viene comunque
+                          riportata in uscita, e non è necessaria impostarla
+                          in ingresso.\\ 
+    \const{EPOLLERR}    & Si è verificata una condizione di errore 
+                          (analogo di \const{POLLERR}); questa condizione
+                          viene comunque riportata in uscita, e non è
+                          necessaria impostarla in ingresso.\\
+    \const{EPOLLHUP}    & Si è verificata una condizione di hung-up.\\
+    \const{EPOLLET}     & Imposta la notifica in modalità \textit{edge
+                            triggered} per il file descriptor associato.\\ 
+    \const{EPOLLONESHOT}& Imposta la modalità \textit{one-shot} per il file
+                          descriptor associato.\footnotemark\\
+    \hline    
+  \end{tabular}
+  \caption{Costanti che identificano i bit del campo \param{events} di
+    \struct{epoll\_event}.}
+  \label{tab:epoll_events}
+\end{table}
+
+\footnotetext{questa modalità è disponibile solo a partire dal kernel 2.6.2.}
+
+Le modalità di utilizzo di \textit{epoll} prevedano che si definisca qual'è
+l'insieme dei file descriptor da tenere sotto controllo tramite un certo
+\textit{epoll descriptor} \param{epfd} attraverso una serie di chiamate a
+\const{EPOLL\_CTL\_ADD}.\footnote{un difetto dell'interfaccia è che queste
+  chiamate devono essere ripetute per ciascun file descriptor, incorrendo in
+  una perdita di prestazioni qualora il numero di file descriptor sia molto
+  grande; per questo è stato proposto di introdurre come estensione una
+  funzione \func{epoll\_ctlv} che consenta di effettuare con una sola chiamata
+  le impostazioni per un blocco di file descriptor.} L'uso di
+\const{EPOLL\_CTL\_MOD} consente in seguito di modificare le modalità di
+osservazione di un file descriptor che sia già stato aggiunto alla lista di
+osservazione.
+
+Le impostazioni di default prevedono che la notifica degli eventi richiesti
+sia effettuata in modalità \textit{level triggered}, a meno che sul file
+descriptor non si sia impostata la modalità \textit{edge triggered},
+registrandolo con \const{EPOLLET} attivo nel campo \var{events}.  Si tenga
+presente che è possibile tenere sotto osservazione uno stesso file descriptor
+su due \textit{epoll descriptor} diversi, ed entrambi riceveranno le
+notifiche, anche se questa pratica è sconsigliata.
+
+Qualora non si abbia più interesse nell'osservazione di un file descriptor lo
+si può rimuovere dalla lista associata a \param{epfd} con
+\const{EPOLL\_CTL\_DEL}; si tenga conto inoltre che i file descriptor sotto
+osservazione che vengono chiusi sono eliminati dalla lista automaticamente e
+non è necessario usare \const{EPOLL\_CTL\_DEL}.
+
+Infine una particolare modalità di notifica è quella impostata con
+\const{EPOLLONESHOT}: a causa dell'implementazione di \textit{epoll} infatti
+quando si è in modalità \textit{edge triggered} l'arrivo in rapida successione
+di dati in blocchi separati\footnote{questo è tipico con i socket di rete, in
+  quanto i dati arrivano a pacchetti.} può causare una generazione di eventi
+(ad esempio segnalazioni di dati in lettura disponibili) anche se la
+condizione è già stata rilevata.\footnote{si avrebbe cioè una rottura della
+  logica \textit{edge triggered}.} 
+
+Anche se la situazione è facile da gestire, la si può evitare utilizzando
+\const{EPOLLONESHOT} per impostare la modalità \textit{one-shot}, in cui la
+notifica di un evento viene effettuata una sola volta, dopo di che il file
+descriptor osservato, pur restando nella lista di osservazione, viene
+automaticamente disattivato,\footnote{la cosa avviene contestualmente al
+  ritorno di \func{epoll\_wait} a causa dell'evento in questione.} e per
+essere riutilizzato dovrà essere riabilitato esplicitamente con una successiva
+chiamata con \const{EPOLL\_CTL\_MOD}.
+
+Una volta impostato l'insieme di file descriptor che si vogliono osservare con
+i relativi eventi, la funzione che consente di attendere l'occorrenza di uno
+di tali eventi è \funcd{epoll\_wait}, il cui prototipo è:
+\begin{prototype}{sys/epoll.h}
+  {int epoll\_wait(int epfd, struct epoll\_event * events, int maxevents, int
+    timeout)}
+  
+  Attende che uno dei file descriptor osservati sia pronto.
+  
+  \bodydesc{La funzione restituisce il numero di file descriptor pronti in
+    caso di successo o $-1$ in caso di errore, nel qual caso \var{errno}
+    assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] il file descriptor \param{epfd} non è valido.
+  \item[\errcode{EFAULT}] il puntatore \param{events} non è valido.
+  \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
+    della scadenza di \param{timeout}.
+  \item[\errcode{EINVAL}] il file descriptor \param{epfd} non è stato ottenuto
+    con \func{epoll\_create}, o \param{maxevents} non è maggiore di zero.
+  \end{errlist}
+}
+\end{prototype}
+
+La funzione si blocca in attesa di un evento per i file descriptor registrati
+nella lista di osservazione di \param{epfd} fino ad un tempo massimo
+specificato in millisecondi tramite l'argomento \param{timeout}. Gli eventi
+registrati vengono riportati in un vettore di strutture \struct{epoll\_event}
+(che deve essere stato allocato in precedenza) all'indirizzo indicato
+dall'argomento \param{events}, fino ad un numero massimo di eventi impostato
+con l'argomento \param{maxevents}.
+
+La funzione ritorna il numero di eventi rilevati, o un valore nullo qualora
+sia scaduto il tempo massimo impostato con \param{timeout}. Per quest'ultimo,
+oltre ad un numero di millisecondi, si può utilizzare il valore nullo, che
+indica di non attendere e ritornare immediatamente,\footnote{anche in questo
+  caso il valore di ritorno sarà nullo.} o il valore $-1$, che indica
+un'attesa indefinita. L'argomento \param{maxevents} dovrà invece essere sempre
+un intero positivo.
+
+Come accennato la funzione restituisce i suoi risultati nel vettore di
+strutture \struct{epoll\_event} puntato da \param{events}; in tal caso nel
+campo \param{events} di ciascuna di esse saranno attivi i flag relativi agli
+eventi accaduti, mentre nel campo \var{data} sarà restituito il valore che era
+stato impostato per il file descriptor per cui si è verificato l'evento quando
+questo era stato registrato con le operazioni \const{EPOLL\_CTL\_MOD} o
+\const{EPOLL\_CTL\_ADD}, in questo modo il campo \var{data} consente di
+identificare il file descriptor.\footnote{ed è per questo che, come accennato,
+  è consuetudine usare per \var{data} il valore del file descriptor stesso.}
+
+Si ricordi che le occasioni per cui \func{epoll\_wait} ritorna dipendono da
+come si è impostata la modalità di osservazione (se \textit{level triggered} o
+\textit{edge triggered}) del singolo file descriptor. L'interfaccia assicura
+che se arrivano più eventi fra due chiamate successive ad \func{epoll\_wait}
+questi vengano combinati. Inoltre qualora su un file descriptor fossero
+presenti eventi non ancora notificati, e si effettuasse una modifica
+dell'osservazione con \const{EPOLL\_CTL\_MOD} questi verrebbero riletti alla
+luce delle modifiche.
+
+Si tenga presente infine che con l'uso della modalità \textit{edge triggered}
+il ritorno di \func{epoll\_wait} indica un file descriptor è pronto e resterà
+tale fintanto che non si sono completamente esaurite le operazioni su di esso.
+Questa condizione viene generalmente rilevata dall'occorrere di un errore di
+\errcode{EAGAIN} al ritorno di una \func{read} o una \func{write},\footnote{è
+  opportuno ricordare ancora una volta che l'uso dell'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 con il fatto che sono stati restituiti meno dati di quelli richiesti.
+
+Come le precedenti \func{select} e \func{poll}, 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 di nuovo 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_sock_multiplexing}.
+
+
+\itindend{epoll}
 
-%\subsection{L'interfaccia di \textit{epoll}}
-%\label{sec:file_epoll}
-% placeholder ...
 
-%da fare
 
 \section{L'accesso \textsl{asincrono} ai file}
 \label{sec:file_asyncronous_access}
@@ -450,59 +905,68 @@ contesto le modalit
 \textsl{asincrona}, quelle cioè in cui un processo non deve bloccarsi in
 attesa della disponibilità dell'accesso al file, ma può proseguire
 nell'esecuzione utilizzando invece un meccanismo di notifica asincrono (di
-norma un segnale), per essere avvisato della possibilità di eseguire le
+norma un segnale, ma esistono anche altre interfacce, come \itindex{inotify}
+\textit{inotify}), per essere avvisato della possibilità di eseguire le
 operazioni di I/O volute.
 
 
-\subsection{Operazioni asincrone sui file}
+\subsection{Il \textit{Signal driven I/O}}
 \label{sec:file_asyncronous_operation}
 
-Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso l'uso
-del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e dei
-  comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è specifico
-  di Linux e BSD.} aprire un file in modalità asincrona, così come è possibile
-attivare in un secondo tempo questa modalità impostando questo flag attraverso
-l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
-sez.~\ref{sec:file_fcntl}). 
-
-In realtà in questo caso non si tratta di eseguire delle operazioni di lettura
-o scrittura del file in modo asincrono (tratteremo questo, che più
-propriamente è detto \textsl{I/O asincrono} in
-sez.~\ref{sec:file_asyncronous_io}), quanto di un meccanismo asincrono di
-notifica delle variazione dello stato del file descriptor aperto in questo
-modo.
-
-Quello che succede in questo caso è che il sistema genera un segnale
-(normalmente \const{SIGIO}, ma è possibile usarne altri con il comando
-\const{F\_SETSIG} di \func{fcntl}) tutte le volte che diventa possibile
-leggere o scrivere dal file descriptor che si è posto in questa modalità. Si
-può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
+Abbiamo accennato in sez.~\ref{sec:file_open} che è possibile, attraverso
+l'uso del flag \const{O\_ASYNC},\footnote{l'uso del flag di \const{O\_ASYNC} e
+  dei comandi \const{F\_SETOWN} e \const{F\_GETOWN} per \func{fcntl} è
+  specifico di Linux e BSD.} aprire un file in modalità asincrona, così come è
+possibile attivare in un secondo tempo questa modalità impostando questo flag
+attraverso l'uso di \func{fcntl} con il comando \const{F\_SETFL} (vedi
+sez.~\ref{sec:file_fcntl}).
+
+In realtà 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 in questo caso è che il
+sistema genera un segnale (normalmente \const{SIGIO}, ma è possibile usarne
+altri con il comando \const{F\_SETSIG} di \func{fcntl}) tutte le volte che
+diventa possibile leggere o scrivere dal file descriptor che si è posto in
+questa modalità.\footnote{questa modalità non è utilizzabile con i file
+  ordinari ma solo con socket, file di terminale o pseudo terminale, e, a
+  partire dal kernel 2.6, anche per fifo e pipe.}
+
+Si può inoltre selezionare, con il comando \const{F\_SETOWN} di \func{fcntl},
 quale processo (o gruppo di processi) riceverà il segnale. Se pertanto si
 effettuano le operazioni di I/O in risposta alla ricezione del segnale non ci
 sarà più la necessità di restare bloccati in attesa della disponibilità di
-accesso ai file; per questo motivo Stevens chiama questa modalità
-\textit{signal driven I/O}.
-
-In questo modo si può evitare l'uso delle funzioni \func{poll} o \func{select}
-che, quando vengono usate con un numero molto grande di file descriptor, non
-hanno buone prestazioni. % aggiungere cenno a epoll quando l'avrò scritta
- In tal caso infatti la maggior parte del loro tempo
-di esecuzione è impegnato ad eseguire una scansione su tutti i file descriptor
-tenuti sotto controllo per determinare quali di essi (in genere una piccola
-percentuale) sono diventati attivi.
+accesso ai file. 
+
+Per questo motivo Stevens, ed anche le pagine di manuale di
+Linux, chiamano questa modalità ``\textit{Signal driven I/O}''.  Questa è
+ancora un'altra modalità di gestione dell'I/O, alternativa all'uso di
+\itindex{epoll} \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
+file descriptor sono più di uno, qual è quello responsabile dell'emissione del
 segnale. Inoltre dato che i segnali normali non si accodano (si ricordi quanto
 illustrato in sez.~\ref{sec:sig_notification}), in presenza di più file
 descriptor attivi contemporaneamente, più segnali emessi nello stesso momento
-verrebbero notificati una volta sola. Linux però supporta le estensioni
-POSIX.1b dei segnali real-time, che vengono accodati e che permettono di
-riconoscere il file descriptor che li ha emessi. In questo caso infatti si può
-fare ricorso alle informazioni aggiuntive restituite attraverso la struttura
-\struct{siginfo\_t}, utilizzando la forma estesa \var{sa\_sigaction} del
-gestore (si riveda quanto illustrato in sez.~\ref{sec:sig_sigaction}).
+verrebbero notificati una volta sola.
+
+Linux però supporta le estensioni POSIX.1b dei segnali real-time, che vengono
+accodati e che permettono di riconoscere il file descriptor che li ha emessi.
+In questo caso infatti si può fare ricorso alle informazioni aggiuntive
+restituite attraverso la struttura \struct{siginfo\_t}, utilizzando la forma
+estesa \var{sa\_sigaction} del gestore installata con il flag
+\const{SA\_SIGINFO} (si riveda quanto illustrato in
+sez.~\ref{sec:sig_sigaction}).
 
 Per far questo però occorre utilizzare le funzionalità dei segnali real-time
 (vedi sez.~\ref{sec:sig_real_time}) impostando esplicitamente con il comando
@@ -522,11 +986,581 @@ risposta a seconda del segnale usato, dato che i segnali real-time supportano
 anche questa funzionalità. In questo modo si può identificare immediatamente
 un file su cui l'accesso è diventato possibile evitando completamente l'uso di
 funzioni come \func{poll} e \func{select}, almeno fintanto che non si satura
-la coda.  Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non
-potendo più assicurare il comportamento corretto per un segnale real-time,
-invierà al suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti
-i segnali in eccesso, e si dovrà allora determinare con un ciclo quali sono i
-file diventati attivi.
+la coda.  
+
+Se infatti si eccedono le dimensioni di quest'ultima, il kernel, non potendo
+più assicurare il comportamento corretto per un segnale real-time, invierà al
+suo posto un solo \const{SIGIO}, su cui si saranno accumulati tutti i segnali
+in eccesso, e si dovrà allora determinare con un ciclo quali sono i file
+diventati attivi. L'unico modo per essere sicuri che questo non avvenga è di
+impostare la lunghezza della coda dei segnali real-time ad una dimensione
+identica al valore massimo del numero di file descriptor
+utilizzabili.\footnote{vale a dire impostare il contenuto di
+  \procfile{/proc/sys/kernel/rtsig-max} allo stesso valore del contenuto di
+  \procfile{/proc/sys/fs/file-max}.}
+
+% TODO fare esempio che usa O_ASYNC
+
+
+\subsection{I meccanismi di notifica asincrona.}
+\label{sec:file_asyncronous_lease}
+
+Una delle domande più frequenti nella programmazione in ambiente unix-like è
+quella di come fare a sapere quando un file viene modificato. La
+risposta\footnote{o meglio la non risposta, tanto che questa nelle Unix FAQ
+  \cite{UnixFAQ} viene anche chiamata una \textit{Frequently Unanswered
+    Question}.} è che nell'architettura classica di Unix questo non è
+possibile. Al contrario di altri sistemi operativi infatti un kernel unix-like
+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\footnote{in genere questo vien fatto inviandogli un segnale di
+  \const{SIGHUP} che, per una convenzione adottata dalla gran parte di detti
+  programmi, causa la rilettura della configurazione.} se il loro file di
+configurazione è stato modificato, perché possano rileggerlo e riconoscere le
+modifiche.
+
+Questa scelta è stata fatta perché provvedere un simile meccanismo a livello
+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 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
+\itindex{polling} \textit{polling}.
+
+Queste nuove funzionalità sono delle estensioni specifiche, non
+standardizzate, che sono disponibili soltanto su Linux (anche se altri kernel
+supportano meccanismi simili). 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}), che divengono disponibili soltanto se si è
+definita la macro \macro{\_GNU\_SOURCE} prima di includere \file{fcntl.h}.
+
+\index{file!lease|(} 
+
+La prima di queste funzionalità è quella del cosiddetto \textit{file lease};
+questo è un meccanismo che consente ad un processo, detto \textit{lease
+  holder}, di essere notificato quando un altro processo, chiamato a sua volta
+\textit{lease breaker}, cerca di eseguire una \func{open} o una
+\func{truncate} sul file del quale l'\textit{holder} detiene il
+\textit{lease}.
+
+La notifica avviene in maniera analoga a come illustrato in precedenza per
+l'uso di \const{O\_ASYNC}: di default viene inviato al \textit{lease holder}
+il segnale \const{SIGIO}, ma questo segnale può essere modificato usando il
+comando \const{F\_SETSIG} di \func{fcntl}.\footnote{anche in questo caso si
+  può rispecificare lo stesso \const{SIGIO}.} Se si è fatto questo\footnote{è
+  in genere è opportuno farlo, come in precedenza, per utilizzare segnali
+  real-time.} e si è installato il 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 il lettura; in quest'ultimo caso però il \textit{lease}
+può essere ottenuto solo se nessun altro processo ha aperto lo stesso file.
+
+Come accennato in sez.~\ref{sec:file_fcntl} il comando di \func{fcntl} che
+consente di acquisire un \textit{file lease} è \const{F\_SETLEASE}, che viene
+utilizzato anche per rilasciarlo. In tal caso il file descriptor \param{fd}
+passato a \func{fcntl} servirà come riferimento per il file su cui si vuole
+operare, mentre per indicare il tipo di operazione (acquisizione o rilascio)
+occorrerà specificare come valore dell'argomento \param{arg} di \func{fcntl}
+uno dei tre valori di tab.~\ref{tab:file_lease_fctnl}.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{F\_RDLCK} & Richiede un \textit{read lease}.\\
+    \const{F\_WRLCK} & Richiede un \textit{write lease}.\\
+    \const{F\_UNLCK} & Rilascia un \textit{file lease}.\\
+    \hline    
+  \end{tabular}
+  \caption{Costanti per i tre possibili valori dell'argomento \param{arg} di
+    \func{fcntl} quando usata con i comandi \const{F\_SETLEASE} e
+    \const{F\_GETLEASE}.} 
+  \label{tab:file_lease_fctnl}
+\end{table}
+
+Se invece si vuole conoscere lo stato di eventuali \textit{file lease}
+occorrerà chiamare \func{fcntl} sul relativo file descriptor \param{fd} con il
+comando \const{F\_GETLEASE}, e si otterrà indietro nell'argomento \param{arg}
+uno dei valori di tab.~\ref{tab:file_lease_fctnl}, che indicheranno la
+presenza del rispettivo tipo di \textit{lease}, o, nel caso di
+\const{F\_UNLCK}, l'assenza di qualunque \textit{file lease}.
+
+Si tenga presente che un processo può mantenere solo un tipo di \textit{lease}
+su un file, e che un \textit{lease} può essere ottenuto solo su file di dati
+(pipe e dispositivi sono quindi esclusi). Inoltre un processo non privilegiato
+può ottenere un \textit{lease} soltanto per un file appartenente ad un
+\acr{uid} corrispondente a quello del processo. Soltanto un processo con
+privilegi di amministratore (cioè con la \itindex{capabilities} capability
+\const{CAP\_LEASE}, 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
+esso,\footnote{in realtà \func{truncate} confligge sempre, mentre \func{open},
+  se eseguita in sola lettura, non confligge se si tratta di un \textit{read
+    lease}.} la funzione si blocca\footnote{a meno di non avere aperto il file
+  con \const{O\_NONBLOCK}, nel qual caso \func{open} fallirebbe con un errore
+  di \errcode{EWOULDBLOCK}.} e viene eseguita la notifica al \textit{lease
+  holder}, così che questo possa completare le sue operazioni sul file e
+rilasciare il \textit{lease}.  In sostanza con un \textit{read lease} si
+rilevano i tentativi di accedere al file per modificarne i dati da parte di un
+altro processo, mentre con un \textit{write lease} si rilevano anche i
+tentativi di accesso in lettura.  Si noti comunque che le operazioni di
+notifica avvengono solo in fase di apertura del file e non sulle singole
+operazioni di lettura e scrittura.
+
+L'utilizzo dei \textit{file lease} consente al \textit{lease holder} di
+assicurare la consistenza di un file, a seconda dei due casi, prima che un
+altro processo inizi con le sue operazioni di scrittura o di lettura su di
+esso. In genere un \textit{lease holder} che riceve una notifica deve
+provvedere a completare le necessarie operazioni (ad esempio scaricare
+eventuali buffer), per poi rilasciare il \textit{lease} così che il
+\textit{lease breaker} possa eseguire le sue operazioni. Questo si fa con il
+comando \const{F\_SETLEASE}, o rimuovendo il \textit{lease} con
+\const{F\_UNLCK}, o, nel caso di \textit{write lease} che confligge con una
+operazione di lettura, declassando il \textit{lease} a lettura con
+\const{F\_RDLCK}.
+
+Se il \textit{lease holder} non provvede a rilasciare il \textit{lease} entro
+il numero di secondi specificato dal parametro di sistema mantenuto in
+\procfile{/proc/sys/fs/lease-break-time} sarà il kernel stesso a rimuoverlo (o
+declassarlo) automaticamente.\footnote{questa è una misura di sicurezza per
+  evitare che un processo blocchi indefinitamente l'accesso ad un file
+  acquisendo un \textit{lease}.} Una volta che un \textit{lease} è stato
+rilasciato o declassato (che questo sia fatto dal \textit{lease holder} o dal
+kernel è lo stesso) le chiamate a \func{open} o \func{truncate} eseguite dal
+\textit{lease breaker} rimaste bloccate proseguono automaticamente.
+
+
+\index{file!dnotify|(}
+
+Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da
+parte di più processi, l'uso dei \textit{file lease} non consente comunque di
+risolvere il problema di rilevare automaticamente quando un file o una
+directory vengono modificati, che è quanto necessario ad esempio ai programma
+di gestione dei file dei vari desktop grafici.
+
+Per risolvere questo problema a partire dal kernel 2.4 è stata allora creata
+un'altra interfaccia,\footnote{si ricordi che anche questa è una interfaccia
+  specifica di Linux che deve essere evitata se si vogliono scrivere programmi
+  portabili, e che le funzionalità illustrate sono disponibili soltanto se è
+  stata definita la macro \macro{\_GNU\_SOURCE}.} chiamata \textit{dnotify},
+che consente di richiedere una notifica quando una directory, o uno qualunque
+dei file in essa contenuti, viene modificato.  Come per i \textit{file lease}
+la notifica avviene di default attraverso il segnale \const{SIGIO}, ma se ne
+può utilizzare un altro.\footnote{e di nuovo, per le ragioni già esposte in
+  precedenza, è opportuno che si utilizzino dei segnali real-time.} Inoltre,
+come in precedenza, si potrà ottenere nel gestore del segnale il file
+descriptor che è stato modificato tramite il contenuto della struttura
+\struct{siginfo\_t}.
+
+\index{file!lease|)}
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{DN\_ACCESS} & Un file è stato acceduto, con l'esecuzione di una fra
+                         \func{read}, \func{pread}, \func{readv}.\\ 
+    \const{DN\_MODIFY} & Un file è stato modificato, con l'esecuzione di una
+                         fra \func{write}, \func{pwrite}, \func{writev}, 
+                         \func{truncate}, \func{ftruncate}.\\ 
+    \const{DN\_CREATE} & È stato creato un file nella directory, con
+                         l'esecuzione di una fra \func{open}, \func{creat},
+                         \func{mknod}, \func{mkdir}, \func{link},
+                         \func{symlink}, \func{rename} (da un'altra
+                         directory).\\
+    \const{DN\_DELETE} & È stato cancellato un file dalla directory con
+                         l'esecuzione di una fra \func{unlink}, \func{rename}
+                         (su un'altra directory), \func{rmdir}.\\
+    \const{DN\_RENAME} & È stato rinominato un file all'interno della
+                         directory (con \func{rename}).\\
+    \const{DN\_ATTRIB} & È stato modificato un attributo di un file con
+                         l'esecuzione di una fra \func{chown}, \func{chmod},
+                         \func{utime}.\\ 
+    \const{DN\_MULTISHOT}& Richiede una notifica permanente di tutti gli
+                         eventi.\\ 
+    \hline    
+  \end{tabular}
+  \caption{Le costanti che identificano le varie classi di eventi per i quali
+    si richiede la notifica con il comando \const{F\_NOTIFY} di \func{fcntl}.} 
+  \label{tab:file_notify}
+\end{table}
+
+Ci si può registrare per le notifiche dei cambiamenti al contenuto di una
+certa directory eseguendo la funzione \func{fcntl} su un file descriptor
+associato alla stessa con il comando \const{F\_NOTIFY}. In questo caso
+l'argomento \param{arg} di \func{fcntl} serve ad indicare per quali classi
+eventi si vuole ricevere la notifica, e prende come valore una maschera
+binaria composta dall'OR aritmetico di una o più delle costanti riportate in
+tab.~\ref{tab:file_notify}.
+
+A meno di non impostare in maniera esplicita una notifica permanente usando il
+valore \const{DN\_MULTISHOT}, la notifica è singola: viene cioè inviata una
+sola volta quando si verifica uno qualunque fra gli eventi per i quali la si è
+richiesta. Questo significa che un programma deve registrarsi un'altra volta
+se desidera essere notificato di ulteriori cambiamenti. Se si eseguono diverse
+chiamate con \const{F\_NOTIFY} e con valori diversi per \param{arg} questi
+ultimi si \textsl{accumulano}; cioè eventuali nuovi classi di eventi
+specificate in chiamate successive vengono aggiunte a quelle già impostate
+nelle precedenti.  Se si vuole rimuovere la notifica si deve invece
+specificare un valore nullo.
+
+\index{file!inotify|(}
+
+Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve
+usare un file descriptor per ciascuna directory che si vuole tenere sotto
+controllo, il che porta facilmente ad avere un eccesso di file aperti. Inoltre
+quando la directory che si controlla è all'interno di un dispositivo
+rimovibile, mantenere il relativo file descriptor aperto comporta
+l'impossibilità di smontare il dispositivo e di rimuoverlo, il che in genere
+complica notevolmente la gestione dell'uso di questi dispositivi.
+
+Un altro problema è che l'interfaccia di \textit{dnotify} consente solo di
+tenere sotto controllo il contenuto di una directory; la modifica di un file
+viene segnalata, ma poi è necessario verificare di quale file si tratta
+(operazione che può essere molto onerosa quando una directory contiene un gran
+numero di file).  Infine l'uso dei segnali come interfaccia di notifica
+comporta tutti i problemi di gestione visti in sez.~\ref{sec:sig_management} e
+sez.~\ref{sec:sig_control}.  Per tutta questa serie di motivi in generale
+quella di \textit{dnotify} viene considerata una interfaccia di usabilità
+problematica.
+
+\index{file!dnotify|)}
+
+Per risolvere i problemi appena illustrati è stata introdotta una nuova
+interfaccia per l'osservazione delle modifiche a file o directory, chiamata
+\textit{inotify}.\footnote{l'interfaccia è disponibile a partire dal kernel
+  2.6.13, le relative funzioni sono state introdotte nelle glibc 2.4.}  Anche
+questa è una interfaccia specifica di Linux (pertanto non deve essere usata se
+si devono scrivere programmi portabili), ed è basata sull'uso di una coda di
+notifica degli eventi associata ad un singolo file descriptor, il che permette
+di risolvere il principale problema di \itindex{dnotify} \textit{dnotify}.  La
+coda viene creata attraverso la funzione \funcd{inotify\_init}, il cui
+prototipo è:
+\begin{prototype}{sys/inotify.h}
+  {int inotify\_init(void)}
+  
+  Inizializza una istanza di \textit{inotify}.
+  
+  \bodydesc{La funzione restituisce un file descriptor in caso di successo, o
+    $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EMFILE}] si è raggiunto il numero massimo di istanze di
+    \textit{inotify} consentite all'utente.
+  \item[\errcode{ENFILE}] si è raggiunto il massimo di file descriptor aperti
+    nel sistema.
+  \item[\errcode{ENOMEM}] non c'è sufficiente memoria nel kernel per creare
+    l'istanza.
+  \end{errlist}
+}
+\end{prototype}
+
+La funzione non prende alcun argomento; inizializza una istanza di
+\textit{inotify} e restituisce un file descriptor attraverso il quale verranno
+effettuate le operazioni di notifica;\footnote{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
+  \procfile{/proc/sys/fs/inotify/max\_user\_instances}.} si tratta di un file
+descriptor speciale che non è associato a nessun file su disco, e che viene
+utilizzato solo per notificare gli eventi che sono stati posti in
+osservazione. Dato che questo file descriptor non è associato a nessun file o
+directory reale, l'inconveniente di non poter smontare un filesystem i cui
+file sono tenuti sotto osservazione viene completamente
+eliminato.\footnote{anzi, una delle capacità dell'interfaccia di
+  \textit{inotify} è proprio quella di notificare il fatto che il filesystem
+  su cui si trova il file o la directory osservata è stato smontato.}
+
+Inoltre trattandosi di un file descriptor a tutti gli effetti, esso potrà
+essere utilizzato come argomento per le funzioni \func{select} e \func{poll} e
+con l'interfaccia di \textit{epoll}; siccome gli eventi vengono notificati
+come dati disponibili in lettura sul file descriptor, dette funzioni
+ritorneranno tutte le volte che si avrà un evento di notifica. Così, invece di
+dover utilizzare i segnali,\footnote{considerati una pessima scelta dal punto
+  di vista dell'interfaccia utente.} si potrà gestire l'osservazione delle
+modifiche con una qualunque delle modalità di \textit{I/O multiplexing}
+illustrate in sez.~\ref{sec:file_multiplexing}.
+
+Infine l'interfaccia di \textit{inotify} consente di mettere sotto
+osservazione, oltre che una directory anche singoli file.  Una volta creata la
+coda di notifica si devono definire gli eventi da tenere sotto osservazione;
+questo viene fatto attraverso una \textsl{lista di osservazione} (o
+\textit{watch list}) che è associata alla coda. Per gestire la lista di
+osservazione l'interfaccia fornisce due funzioni, la prima di queste è
+\funcd{inotify\_add\_watch}, il cui prototipo è:
+\begin{prototype}{sys/inotify.h}
+  {int inotify\_add\_watch(int fd, const char *pathname, uint32\_t mask)}
+
+  Aggiunge un evento di osservazione alla lista di osservazione di \param{fd}.
+
+  \bodydesc{La funzione restituisce un valore positivo in caso di successo, o
+    $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EACCESS}] non si ha accesso in lettura al file indicato.
+  \item[\errcode{EINVAL}] \param{mask} non contiene eventi legali o \param{fd}
+    non è un filesystem di \textit{inotify}.
+  \item[\errcode{ENOSPC}] si è raggiunto il numero massimo di voci di
+    osservazione o il kernel non ha potuto allocare una risorsa necessaria.
+  \end{errlist}
+  ed inoltre \errval{EFAULT}, \errval{ENOMEM} e \errval{EBADF}.}
+\end{prototype}
+
+La funzione consente di creare un ``\textsl{osservatore}'' (il cosiddetto
+``\textit{watch}'') nella lista di osservazione di una coda di notifica, che
+deve essere indicata specificando il file descriptor ad essa associato
+nell'argomento \param{fd}.\footnote{questo ovviamente dovrà essere un file
+  descriptor creato con \func{inotify\_init}.}  Il file o la directory da
+porre sotto osservazione vengono invece indicati per nome, da passare
+nell'argomento \param{pathname}.  Infine il terzo argomento, \param{mask},
+indica che tipo di eventi devono essere tenuti sotto osservazione e le
+modalità della stessa.  L'operazione può essere ripetuta per tutti i file e le
+directory che si vogliono tenere sotto osservazione,\footnote{anche in questo
+  caso c'è un limite massimo che di default è pari a 8192, ed anche questo
+  valore può essere cambiato con \func{sysctl} o usando il file
+  \procfile{/proc/sys/fs/inotify/max\_user\_watches}.} e si utilizzerà sempre
+un solo file descriptor.
+
+Il tipo di evento che si vuole osservare deve essere specificato
+nell'argomento \param{mask} come maschera binaria, combinando i valori delle
+costanti riportate in tab.~\ref{tab:inotify_event_watch} che identificano i
+singoli bit della maschera ed il relativo significato. In essa si sono marcati
+con un ``$\bullet$'' gli eventi che, quando specificati per una directory,
+vengono osservati anche su tutti i file che essa contiene.  Nella seconda
+parte della tabella si sono poi indicate alcune combinazioni predefinite dei
+flag della prima parte.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|c|p{10cm}|}
+    \hline
+    \textbf{Flag}  & & \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'inode (o sugli attributi
+                                          estesi, vedi
+                                          sez.~\ref{sec:file_xattr}).\\ 
+    \const{IN\_CLOSE\_WRITE}  &$\bullet$& È stato chiuso un file aperto in
+                                          scrittura.\\  
+    \const{IN\_CLOSE\_NOWRITE}&$\bullet$& È stato chiuso un file aperto in
+                                          sola lettura.\\
+    \const{IN\_CREATE}        &$\bullet$& È stato creato un file o una
+                                          directory in una directory sotto
+                                          osservazione.\\  
+    \const{IN\_DELETE}        &$\bullet$& È stato cancellato un file o una
+                                          directory in una directory sotto
+                                          osservazione.\\ 
+    \const{IN\_DELETE\_SELF}  &       &   È stato cancellato il file (o la
+                                          directory) sotto osservazione.\\ 
+    \const{IN\_MODIFY}        &$\bullet$& È stato modificato il file.\\ 
+    \const{IN\_MOVE\_SELF}    &         & è stato rinominato il file (o la
+                                          directory) sotto osservazione.\\ 
+    \const{IN\_MOVED\_FROM}   &$\bullet$& Un file è stato spostato fuori dalla
+                                          directory sotto osservazione.\\ 
+    \const{IN\_MOVED\_TO}     &$\bullet$& Un file è stato spostato nella
+                                          directory sotto osservazione.\\ 
+    \const{IN\_OPEN}          &$\bullet$& Un file è stato aperto.\\ 
+    \hline    
+    \const{IN\_CLOSE}         & --      & Combinazione di
+                                          \const{IN\_CLOSE\_WRITE} e
+                                          \const{IN\_CLOSE\_NOWRITE}.\\  
+    \const{IN\_MOVE}          & --      & Combinazione di
+                                          \const{IN\_MOVED\_FROM} e
+                                          \const{IN\_MOVED\_TO}.\\
+    \const{IN\_ALL\_EVENTS}   & --      & Combinazione di tutti i flag
+                                          possibili.\\
+    \hline    
+  \end{tabular}
+  \caption{Le costanti che identificano i valori per la maschera binaria
+    dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano il
+    tipo di evento da tenere sotto osservazione.} 
+  \label{tab:inotify_event_watch}
+\end{table}
+
+Oltre ai flag di tab.~\ref{tab:inotify_event_watch}, che indicano il tipo di
+evento da osservare e che vengono utilizzati anche in uscita per indicare il
+tipo di evento avvenuto, \func{inotify\_add\_watch} supporta ulteriori
+flag,\footnote{i flag \const{IN\_DONT\_FOLLOW}, \const{IN\_MASK\_ADD} e
+  \const{IN\_ONLYDIR} sono stati introdotti a partire dalle glibc 2.5, se si
+  usa la versione 2.4 è necessario definirli a mano.}  riportati in
+tab.~\ref{tab:inotify_add_watch_flag}, che indicano le modalità di
+osservazione (da passare sempre nell'argomento \param{mask}) e che al
+contrario dei precedenti non vengono mai impostati nei risultati in uscita.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Flag}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IN\_DONT\_FOLLOW}& Non dereferenzia \param{pathname} se questo è un
+                              link simbolico.\\
+    \const{IN\_MASK\_ADD}   & Aggiunge a quelli già impostati i flag indicati
+                              nell'argomento \param{mask}, invece di
+                              sovrascriverli.\\
+    \const{IN\_ONESHOT}     & Esegue l'osservazione su \param{pathname} per una
+                              sola volta, rimuovendolo poi dalla \textit{watch
+                                list}.\\ 
+    \const{IN\_ONLYDIR}     & Se \param{pathname} è una directory riporta
+                              soltanto gli eventi ad essa relativi e non
+                              quelli per i file che contiene.\\ 
+    \hline    
+  \end{tabular}
+  \caption{Le costanti che identificano i valori per la maschera binaria
+    dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano le
+    modalità di osservazione.} 
+  \label{tab:inotify_add_watch_flag}
+\end{table}
+
+Se non esiste nessun \textit{watch} per il file o la directory specificata
+questo verrà creato per gli eventi specificati dall'argomento \param{mask},
+altrimenti la funzione sovrascriverà le impostazioni precedenti, a meno che
+non si sia usato il flag \const{IN\_MASK\_ADD}, nel qual caso gli eventi
+specificati saranno aggiunti a quelli già presenti.
+
+Come accennato quando si tiene sotto osservazione una directory vengono
+restituite le informazioni sia riguardo alla directory stessa che ai file che
+essa contiene; questo comportamento può essere disabilitato utilizzando il
+flag \const{IN\_ONLYDIR}, che richiede di riportare soltanto gli eventi
+relativi alla directory stessa. Si tenga presente inoltre che quando si
+osserva una directory vengono riportati solo gli eventi sui file che essa
+contiene direttamente, non quelli relativi a file contenuti in eventuali
+sottodirectory; se si vogliono osservare anche questi sarà necessario creare
+ulteriori \textit{watch} per ciascuna sottodirectory.
+
+Infine usando il flag \const{IN\_ONESHOT} è possibile richiedere una notifica
+singola;\footnote{questa funzionalità però è disponibile soltato a partire dal
+  kernel 2.6.16.} una volta verificatosi uno qualunque fra gli eventi
+richiesti con \func{inotify\_add\_watch} l'\textsl{osservatore} verrà
+automaticamente rimosso dalla lista di osservazione e nessun ulteriore evento
+sarà più notificato.
+
+In caso di successo \func{inotify\_add\_watch} ritorna un intero positivo,
+detto \textit{watch descriptor}; è tramite questo valore che si identifica
+univocamente un \textsl{osservatore} su una coda di notifica, sia per quanto
+riguarda i risultati restituiti da \textit{inotify}, che per quanto riguarda
+la eventuale rimozione dello stesso; la seconda funzione per la gestione delle
+liste di osservazione è infatti \funcd{inotify\_rm\_watch}, che permette di
+rimuovere un \textsl{osservatore}; il suo prototipo è:
+\begin{prototype}{sys/inotify.h}
+  {int inotify\_rm\_watch(int fd, uint32\_t wd)}
+
+  Rimuove un \textsl{osservatore} da una coda di notifica.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo, o $-1$ in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+  \item[\errcode{EBADF}] non si è specificato in \param{fd} un file descriptor
+    valido.
+  \item[\errcode{EINVAL}] il valore di \param{wd} non è corretto, o \param{fd}
+    non è associato ad una coda di notifica.
+  \end{errlist}
+}
+\end{prototype}
+
+La funzione rimuove dalla coda di notifica identificata dall'argomento
+\param{fd} l'osservatore identificato dal \textit{watch descriptor}
+\param{wd};\footnote{ovviamente deve essere usato per questo argomento un
+  valore ritornato da \func{inotify\_add\_watch}, altrimenti si avrà un errore
+  di \errval{EINVAL}.} inoltre, contemporaneamente alla rimozione
+dell'osservatore, sulla coda di notifica verrà generato un evento di tipo
+\const{IN\_IGNORED} (vedi tab.~\ref{tab:inotify_read_event_flag}).
+
+
+Oltre che per la rimozione, il \textit{watch descriptor} viene usato anche per
+identificare l'evento a cui si fa riferimento nella lista dei risultati
+restituiti da \textit{inotify}; questi ultimi infatti vengono notificati alle
+applicazioni che usano l'interfaccia di \textit{inotify} come dati presenti in
+lettura su file descriptor creato con \func{inotify\_init}. 
+
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/inotify_event.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{inotify\_event}.}
+  \label{fig:inotify_event}
+\end{figure}
+
+
+Inoltre l'interfaccia di \textit{inotify} permette di conoscere, come avviene
+per i file descriptor associati ai socket (si veda al proposito quanto
+trattato in sez.~\ref{sec:sock_ioctl_IP}) il numero di byte disponibili in
+lettura sul nostro file descriptor, utilizzando su di esso l'operazione
+\const{FIONREAD} con \func{ioctl}.\footnote{questa è una delle operazioni
+  speciali (che abbiamo visto in sez.~\ref{sec:file_ioctl}) che nel caso è
+  disponibile solo per i socket e per i file descriptor creati con
+  \func{inotify\_init}.} Questo consente anche di ottenere rapidamente il
+numero di file che sono cambiati.
+
+
+
+
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Flag}  & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{IN\_IGNORED}    & .\\
+    \const{IN\_ISDIR}      & .\\
+    \const{IN\_Q\_OVERFLOW}& .\\
+    \const{IN\_UNMOUNT}    & .\\
+    \hline    
+  \end{tabular}
+  \caption{Le costanti che identificano i flag aggiuntivi usati nella maschera
+    binaria del campo \var{mask} di \structd{inotify\_event}.} 
+  \label{tab:inotify_read_event_flag}
+\end{table}
+
+
+
+% TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
+% TODO e man inotify
+
+\index{file!inotify|)}
+
+
+% TODO inserire anche eventfd (vedi http://lwn.net/Articles/233462/)
+% e le restanti signalfd e timerfd introdotte con il 2.6.22
+% o trovargli un posto migliore
 
 
 \subsection{L'interfaccia POSIX per l'I/O asincrono}
@@ -541,22 +1575,22 @@ possibile effettuare una richiesta preventiva di dati, in modo da poter
 effettuare in contemporanea le operazioni di calcolo e quelle di I/O.
 
 Benché la modalità di apertura asincrona di un file possa risultare utile in
-varie occasioni (in particolar modo con i socket\index{socket} e gli altri
-file per i quali le funzioni di I/O sono \index{system call lente}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, che prevede un insieme di funzioni dedicate per la
-lettura e la scrittura dei file, completamente separate rispetto a quelle
-usate normalmente.
+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} 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, che prevede un insieme di funzioni dedicate per la lettura e la
+scrittura dei file, completamente separate rispetto a quelle usate
+normalmente.
 
 In generale questa interfaccia è completamente astratta e può essere
 implementata sia direttamente nel kernel, che in user space attraverso l'uso
-di thread. Al momento esiste una sola versione stabile di questa interfaccia,
-quella delle \acr{glibc}, che è realizzata completamente in user space, ed
-accessibile linkando i programmi con la libreria \file{librt}. Nei kernel
-della nuova serie è stato anche introdotta (a partire dal 2.5.32) un nuovo
-layer per l'I/O asincrono.
+di thread. Per le versioni del kernel meno recenti esiste una implementazione
+di questa interfaccia fornita delle \acr{glibc}, che è realizzata
+completamente in user space, ed è accessibile linkando i programmi con la
+libreria \file{librt}. Nelle versioni più recenti (a partire dalla 2.5.32) è
+stato introdotto direttamente nel kernel un nuovo layer per l'I/O asincrono.
 
 Lo standard 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
@@ -663,8 +1697,8 @@ richiesta, o in caso di errore. Non 
 \errcode{EINVAL} siano rilevati immediatamente al momento della chiamata,
 potrebbero anche emergere nelle fasi successive delle operazioni. Lettura e
 scrittura avvengono alla posizione indicata da \var{aio\_offset}, a meno che
-il file non sia stato aperto in \textit{append mode} (vedi
-sez.~\ref{sec:file_open}), nel qual caso le scritture vengono effettuate
+il file non sia stato aperto in \itindex{append~mode} \textit{append mode}
+(vedi sez.~\ref{sec:file_open}), nel qual caso le scritture vengono effettuate
 comunque alla fine de file, nell'ordine delle chiamate a \func{aio\_write}.
 
 Si tenga inoltre presente che deallocare la memoria indirizzata da
@@ -734,11 +1768,11 @@ esaurimento.
 
 Oltre alle operazioni di lettura e scrittura l'interfaccia POSIX.1b mette a
 disposizione un'altra operazione, quella di sincronizzazione dell'I/O,
-compiuta dalla funzione \func{aio\_fsync}, che ha lo stesso effetto della
+compiuta dalla funzione \funcd{aio\_fsync}, che ha lo stesso effetto della
 analoga \func{fsync}, ma viene eseguita in maniera asincrona; il suo prototipo
 è:
 \begin{prototype}{aio.h}
-{ssize\_t aio\_return(int op, struct aiocb *aiocbp)} 
+{int aio\_fsync(int op, struct aiocb *aiocbp)} 
 
 Richiede la sincronizzazione dei dati per il file indicato da \param{aiocbp}.
   
@@ -764,7 +1798,7 @@ operazioni di sincronizzazione dei dati saranno completate.
 
 In alcuni casi può essere necessario interrompere le operazioni (in genere
 quando viene richiesta un'uscita immediata dal programma), per questo lo
-standard POSIX.1b prevede una funzioni apposita, \funcd{aio\_cancel}, che
+standard POSIX.1b prevede una funzione apposita, \funcd{aio\_cancel}, che
 permette di cancellare una operazione richiesta in precedenza; il suo
 prototipo è:
 \begin{prototype}{aio.h}
@@ -785,10 +1819,9 @@ valore di \param{aiocbp}.  Quando una operazione viene cancellata una
 successiva chiamata ad \func{aio\_error} riporterà \errcode{ECANCELED} come
 codice di errore, ed il suo codice di ritorno sarà -1, inoltre il meccanismo
 di notifica non verrà invocato. Se si specifica una operazione relativa ad un
-altro file descriptor il risultato è indeterminato.
-
-In caso di successo, i possibili valori di ritorno per \func{aio\_cancel} sono
-tre (anch'essi definiti in \file{aio.h}):
+altro file descriptor il risultato è indeterminato.  In caso di successo, i
+possibili valori di ritorno per \func{aio\_cancel} (anch'essi definiti in
+\file{aio.h}) sono tre:
 \begin{basedescript}{\desclabelwidth{3.0cm}}
 \item[\const{AIO\_ALLDONE}] indica che le operazioni di cui si è richiesta la
   cancellazione sono state già completate,
@@ -863,29 +1896,28 @@ lettura o scrittura; il suo prototipo 
   }
 \end{prototype}
 
-La funzione esegue la richiesta delle \param{nent} operazioni indicate dalla
-lista \param{list}; questa deve contenere gli indirizzi di altrettanti
-\textit{control block}, opportunamente inizializzati; in particolare nel caso
-dovrà essere specificato il tipo di operazione tramite il campo
-\var{aio\_lio\_opcode}, che può prendere i tre valori:
+La funzione esegue la richiesta delle \param{nent} operazioni indicate nella
+lista \param{list} che deve contenere gli indirizzi di altrettanti
+\textit{control block} opportunamente inizializzati; in particolare 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.
 \item[\const{LIO\_NOP}] non si effettua nessuna operazione.
 \end{basedescript}
-l'ultimo valore viene usato quando si ha a che fare con un vettore di
-dimensione fissa, per poter specificare solo alcune operazioni, o quando si è
-dovuto cancellare delle operazioni e si deve ripetere la richiesta per quelle
-non completate.
+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
+sono dovute cancellare delle operazioni e si deve ripetere la richiesta per
+quelle non completate.
 
-L'argomento \param{mode} permette di stabilire il comportamento della
-funzione, se viene specificato il valore \const{LIO\_WAIT} la funzione si
-blocca fino al completamento di tutte le operazioni richieste; se invece si
-specifica \const{LIO\_NOWAIT} la funzione ritorna immediatamente dopo aver
-messo in coda tutte le richieste. In questo 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 per il campo \var{aio\_sigevent}
-di \struct{aiocb}.
+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
+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
+per il campo \var{aio\_sigevent} di \struct{aiocb}.
 
 
 \section{Altre modalità di I/O avanzato}
@@ -896,7 +1928,8 @@ Oltre alle precedenti modalit
 accesso ai file più evolute rispetto alle normali funzioni di lettura e
 scrittura che abbiamo esaminato in sez.~\ref{sec:file_base_func}. In questa
 sezione allora prenderemo in esame le interfacce per l'\textsl{I/O
-  vettorizzato} e per l'\textsl{I/O mappato in memoria}.
+  vettorizzato} e per l'\textsl{I/O mappato in memoria} e la funzione
+\func{sendfile}.
 
 
 \subsection{I/O vettorizzato}
@@ -921,37 +1954,34 @@ prototipi sono:
 \begin{functions}
   \headdecl{sys/uio.h}
   
-  \funcdecl{int readv(int fd, const struct iovec *vector, int count)} Esegue
-  una lettura vettorizzata da \param{fd} nei \param{count} buffer specificati
-  da \param{vector}.
-  
-  \funcdecl{int writev(int fd, const struct iovec *vector, int count)} Esegue
-  una scrittura vettorizzata da \param{fd} nei \param{count} buffer
-  specificati da \param{vector}.
+  \funcdecl{int readv(int fd, const struct iovec *vector, int count)} 
+  \funcdecl{int writev(int fd, const struct iovec *vector, int count)} 
+
+  Eseguono rispettivamente una lettura o una scrittura vettorizzata.
   
   \bodydesc{Le funzioni restituiscono il numero di byte letti o scritti in
     caso di successo, e -1 in caso di errore, nel qual caso \var{errno}
     assumerà uno dei valori:
   \begin{errlist}
-  \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato.
   \item[\errcode{EINVAL}] si è specificato un valore non valido per uno degli
     argomenti (ad esempio \param{count} è maggiore di \const{MAX\_IOVEC}).
   \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima di
     di avere eseguito una qualunque lettura o scrittura.
   \item[\errcode{EAGAIN}] \param{fd} è stato aperto in modalità non bloccante e
   non ci sono dati in lettura.
-  \item[\errcode{EOPNOTSUPP}] La coda delle richieste è momentaneamente piena.
+  \item[\errcode{EOPNOTSUPP}] la coda delle richieste è momentaneamente piena.
   \end{errlist}
-  ed inoltre \errval{EISDIR}, \errval{ENOMEM}, \errval{EFAULT} (se non sono
-  stato allocati correttamente i buffer specificati nei campi
-  \func{iov\_base}), più tutti gli ulteriori errori che potrebbero avere le
-  usuali funzioni di lettura e scrittura eseguite su \param{fd}.}
+  ed anche \errval{EISDIR}, \errval{EBADF}, \errval{ENOMEM}, \errval{EFAULT}
+  (se non sono stati allocati correttamente i buffer specificati nei campi
+  \var{iov\_base}), più gli eventuali errori delle funzioni di lettura e
+  scrittura eseguite su \param{fd}.}
 \end{functions}
 
-Entrambe le funzioni usano una struttura \struct{iovec}, definita in
-fig.~\ref{fig:file_iovec}, che definisce dove i dati devono essere letti o
-scritti. Il primo campo, \var{iov\_base}, contiene l'indirizzo del buffer ed
-il secondo, \var{iov\_len}, la dimensione dello stesso. 
+Entrambe le funzioni usano una struttura \struct{iovec}, la cui definizione è
+riportata in fig.~\ref{fig:file_iovec}, che definisce dove i dati devono
+essere letti o scritti ed in che quantità. Il primo campo della struttura,
+\var{iov\_base}, contiene l'indirizzo del buffer ed il secondo,
+\var{iov\_len}, la dimensione dello stesso.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -964,61 +1994,70 @@ il secondo, \var{iov\_len}, la dimensione dello stesso.
   \label{fig:file_iovec}
 \end{figure}
 
-I buffer da utilizzare sono indicati attraverso l'argomento \param{vector} che
-è un vettore di strutture \struct{iovec}, la cui lunghezza è specificata da
-\param{count}.  Ciascuna struttura dovrà essere inizializzata per
-opportunamente per indicare i vari buffer da/verso i quali verrà eseguito il
-trasferimento dei dati. Essi verranno letti (o scritti) nell'ordine in cui li
-si sono specificati nel vettore \param{vector}.
+La lista dei buffer da utilizzare viene indicata attraverso l'argomento
+\param{vector} che è un vettore di strutture \struct{iovec}, la cui lunghezza
+è specificata dall'argomento \param{count}.  Ciascuna struttura dovrà essere
+inizializzata opportunamente per indicare i vari buffer da e verso i quali
+verrà eseguito il trasferimento dei dati. Essi verranno letti (o scritti)
+nell'ordine in cui li si sono specificati nel vettore \param{vector}.
 
 
 \subsection{File mappati in memoria}
 \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 cap.~\ref{cha: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} \index{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. Il meccanismo è
-illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del file viene
-riportata direttamente nello spazio degli indirizzi del programma. Tutte le
-operazioni su questa zona verranno riportate indietro sul file dal meccanismo
-della memoria virtuale\index{memoria virtuale} che trasferirà il contenuto di
-quel segmento sul file invece che nella swap, per cui si può parlare tanto di
-file mappato in memoria, quanto di memoria mappata su file.
-
+file in una sezione dello spazio di indirizzi del processo. 
+ che lo ha allocato
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=7.cm]{img/mmap_layout}
+  \includegraphics[width=10cm]{img/mmap_layout}
   \caption{Disposizione della memoria di un processo quando si esegue la
   mappatura in memoria di un file.}
   \label{fig:file_mmap_layout}
 \end{figure}
 
-Tutto questo comporta una notevole semplificazione delle operazioni di I/O, in
-quanto non sarà più necessario utilizzare dei buffer intermedi su cui
-appoggiare i dati da traferire, ma questi potranno essere acceduti
-direttamente nella sezione di memoria mappata; inoltre questa interfaccia è
-più efficiente delle usuali funzioni di I/O, in quanto permette di caricare in
-memoria solo le parti del file che sono effettivamente usate ad un dato
-istante.
-
-Infatti, dato che l'accesso è fatto direttamente attraverso la memoria
-virtuale,\index{memoria virtuale} la sezione di memoria mappata su cui si
-opera sarà a sua volta letta o scritta sul file una pagina alla volta e solo
-per le parti effettivamente usate, il tutto in maniera completamente
+Il meccanismo è illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del
+file viene \textsl{mappata} direttamente nello spazio degli indirizzi del
+programma.  Tutte le operazioni di lettura e scrittura su variabili contenute
+in questa zona di memoria verranno eseguite leggendo e scrivendo dal contenuto
+del file attraverso il sistema della memoria virtuale \index{memoria~virtuale}
+che in maniera analoga a quanto avviene per le pagine che vengono salvate e
+rilette nella swap, si incaricherà di sincronizzare il contenuto di quel
+segmento di memoria con quello del file mappato su di esso.  Per questo motivo
+si può parlare tanto di \textsl{file mappato in memoria}, quanto di
+\textsl{memoria mappata su file}.
+
+L'uso del \textit{memory-mapping} comporta una notevole semplificazione delle
+operazioni di I/O, in quanto non sarà più necessario utilizzare dei buffer
+intermedi su cui appoggiare i dati da traferire, poiché questi potranno essere
+acceduti direttamente nella sezione di memoria mappata; inoltre questa
+interfaccia è più efficiente delle usuali funzioni di I/O, in quanto permette
+di caricare in memoria solo le parti del file che sono effettivamente usate ad
+un dato istante.
+
+Infatti, dato che l'accesso è fatto direttamente attraverso la
+\index{memoria~virtuale} memoria virtuale, la sezione di memoria mappata su
+cui si opera sarà a sua volta letta o scritta sul file una pagina alla volta e
+solo per le parti effettivamente usate, il tutto in maniera completamente
 trasparente al processo; l'accesso alle pagine non ancora caricate avverrà
 allo stesso modo con cui vengono caricate in memoria le pagine che sono state
-salvate sullo swap.  Infine in situazioni in cui la memoria è scarsa, le
-pagine che mappano un file vengono salvate automaticamente, così come le
-pagine dei programmi vengono scritte sulla swap; questo consente di accedere
-ai file su dimensioni il cui solo limite è quello dello spazio di indirizzi
-disponibile, e non della memoria su cui possono esserne lette delle porzioni.
-
-L'interfaccia prevede varie funzioni per la gestione del \textit{memory mapped
-  I/O}, la prima di queste è \funcd{mmap}, che serve ad eseguire la mappatura
-in memoria di un file; il suo prototipo è:
+salvate sullo swap.
+
+Infine in situazioni in cui la memoria è scarsa, le pagine che mappano un file
+vengono salvate automaticamente, così come le pagine dei programmi vengono
+scritte sulla swap; questo consente di accedere ai file su dimensioni il cui
+solo limite è quello dello spazio di indirizzi disponibile, e non della
+memoria su cui possono esserne lette delle porzioni.
+
+L'interfaccia POSIX implementata da Linux prevede varie funzioni per la
+gestione del \textit{memory mapped I/O}, la prima di queste, che serve ad
+eseguire la mappatura in memoria di un file, è \funcd{mmap}; il suo prototipo
+è:
 \begin{functions}
   
   \headdecl{unistd.h}
@@ -1027,7 +2066,7 @@ in memoria di un file; il suo prototipo 
   \funcdecl{void * mmap(void * start, size\_t length, int prot, int flags, int
     fd, off\_t offset)}
   
-  Esegue la mappatura in memoria del file \param{fd}.
+  Esegue la mappatura in memoria della sezione specificata del file \param{fd}.
   
   \bodydesc{La funzione restituisce il puntatore alla zona di memoria mappata
     in caso di successo, e \const{MAP\_FAILED} (-1) in caso di errore, nel
@@ -1045,11 +2084,18 @@ in memoria di un file; il suo prototipo 
       dimensione delle pagine).
     \item[\errcode{ETXTBSY}] Si è impostato \const{MAP\_DENYWRITE} ma
       \param{fd} è aperto in scrittura.
-    \item[\errcode{EAGAIN}] Il file è bloccato, o si è bloccata troppa memoria.
+    \item[\errcode{EAGAIN}] Il file è bloccato, o si è bloccata troppa memoria
+      rispetto a quanto consentito dai limiti di sistema (vedi
+      sez.~\ref{sec:sys_resource_limit}).
     \item[\errcode{ENOMEM}] Non c'è memoria o si è superato il limite sul
       numero di mappature possibili.
     \item[\errcode{ENODEV}] Il filesystem di \param{fd} non supporta il memory
       mapping.
+    \item[\errcode{EPERM}] L'argomento \param{prot} ha richiesto
+      \const{PROT\_EXEC}, ma il filesystem di \param{fd} è montato con
+      l'opzione \texttt{noexec}.
+    \item[\errcode{ENFILE}] Si è superato il limite del sistema sul numero di
+      file aperti (vedi sez.~\ref{sec:sys_resource_limit}).
     \end{errlist}
   }
 \end{functions}
@@ -1083,16 +2129,16 @@ multiplo della dimensione di una pagina di memoria.
 Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux
   la memoria reale è divisa in pagine: ogni processo vede la sua memoria
   attraverso uno o più segmenti lineari di memoria virtuale.  Per ciascuno di
-  questi segmenti il kernel mantiene nella \textit{page table} la mappatura
-  sulle pagine di memoria reale, ed le modalità di accesso (lettura,
-  esecuzione, scrittura); una loro violazione causa quella che si chiama una
-  \textit{segment violation}, e la relativa emissione del segnale
-  \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere
+  questi segmenti il kernel mantiene nella \itindex{page~table} \textit{page
+    table} la mappatura sulle pagine di memoria reale, ed le modalità di
+  accesso (lettura, esecuzione, scrittura); una loro violazione causa quella
+  che si chiama una \textit{segment violation}, e la relativa emissione del
+  segnale \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere
 specificato come maschera binaria ottenuta dall'OR di uno o più dei valori
 riportati in tab.~\ref{tab:file_mmap_flag}; il valore specificato deve essere
 compatibile con la modalità di accesso con cui si è aperto il file.
 
-L'argomento \param{flags} specifica infine qual'è il tipo di oggetto mappato,
+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
 mantenute private al processo che le ha effettuate. Deve essere specificato
@@ -1102,7 +2148,7 @@ tab.~\ref{tab:file_mmap_flag}.
 \begin{table}[htb]
   \centering
   \footnotesize
-  \begin{tabular}[c]{|l|p{10cm}|}
+  \begin{tabular}[c]{|l|p{11cm}|}
     \hline
     \textbf{Valore} & \textbf{Significato} \\
     \hline
@@ -1111,88 +2157,112 @@ tab.~\ref{tab:file_mmap_flag}.
                              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. \\
+                             alle dimensioni di una pagina.\\
     \const{MAP\_SHARED}    & I cambiamenti sulla memoria mappata vengono
                              riportati sul file e saranno immediatamente
                              visibili agli altri processi che mappano lo stesso
                              file.\footnotemark Il file su disco però non sarà
                              aggiornato fino alla chiamata di \func{msync} o
-                             \func{unmap}), e solo allora le modifiche saranno
+                             \func{munmap}), e solo allora le modifiche saranno
                              visibili per l'I/O convenzionale. Incompatibile
-                             con \const{MAP\_PRIVATE}. \\ 
+                             con \const{MAP\_PRIVATE}.\\ 
     \const{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.  Le modifiche sono mantenute attraverso
-                             il meccanismo del 
-                             \textit{copy on write}\index{copy on write} e
+                             il meccanismo del \textit{copy on
+                               write} \itindex{copy~on~write} e 
                              salvate su swap in caso di necessità. Non è
                              specificato se i cambiamenti sul file originale
                              vengano riportati sulla regione
-                             mappata. Incompatibile con \const{MAP\_SHARED}. \\
+                             mappata. Incompatibile con \const{MAP\_SHARED}.\\
     \const{MAP\_DENYWRITE} & In Linux viene ignorato per evitare
-                             \textit{DoS}\index{DoS} (veniva usato per
-                             segnalare che tentativi di scrittura sul file
-                             dovevano fallire con \errcode{ETXTBSY}).\\
-    \const{MAP\_EXECUTABLE}& Ignorato. \\
+                             \textit{DoS} \itindex{Denial~of~Service~(DoS)}
+                             (veniva usato per segnalare che tentativi di
+                             scrittura sul file dovevano fallire con
+                             \errcode{ETXTBSY}).\\ 
+    \const{MAP\_EXECUTABLE}& Ignorato.\\
     \const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva
-                             delle pagine di swap ad uso del meccanismo di
-                             \textit{copy on write}\index{copy on write}
+                             delle pagine di swap ad uso del meccanismo del
+                             \textit{copy on write} \itindex{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 \const{SIGSEGV}. \\
+                             un \const{SIGSEGV}.\\
     \const{MAP\_LOCKED}    & Se impostato impedisce lo swapping delle pagine
-                             mappate. \\
-    \const{MAP\_GROWSDOWN} & Usato per gli stack. Indica 
+                             mappate.\\
+    \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} stack. Indica 
                              che la mappatura deve essere effettuata con gli
                              indirizzi crescenti verso il basso.\\
     \const{MAP\_ANONYMOUS} & La mappatura non è associata a nessun file. Gli
                              argomenti \param{fd} e \param{offset} sono
                              ignorati.\footnotemark\\
     \const{MAP\_ANON}      & Sinonimo di \const{MAP\_ANONYMOUS}, deprecato.\\
-    \const{MAP\_FILE}      & Valore di compatibilità, deprecato.\\
+    \const{MAP\_FILE}      & Valore di compatibilità, ignorato.\\
+    \const{MAP\_32BIT}     & Esegue la mappatura sui primi 2GiB 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}.\\
+    \const{MAP\_POPULATE}  & Esegue il \itindex{prefaulting}
+                             \textit{prefaulting} delle pagine di memoria
+                             necessarie alla mappatura.\\
+    \const{MAP\_NONBLOCK}  & Esegue un \textit{prefaulting} più limitato che
+                             non causa I/O.\footnotemark\\
+%     \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
+%                              mappata con \func{mremap}, proposto ma pare non
+%                              implementato.\\
     \hline
   \end{tabular}
   \caption{Valori possibili dell'argomento \param{flag} di \func{mmap}.}
   \label{tab:file_mmap_flag}
 \end{table}
 
-\footnotetext{Dato che tutti faranno riferimento alle stesse pagine di
-  memoria.}  
-\footnotetext{L'uso di questo flag con \const{MAP\_SHARED} è
-  stato implementato in Linux a partire dai kernel della serie 2.4.x.}
 
 Gli effetti dell'accesso ad una zona di memoria mappata su file possono essere
 piuttosto complessi, essi si possono comprendere solo tenendo presente che
-tutto quanto è comunque basato sul basato sul meccanismo della memoria
-virtuale.\index{memoria virtuale} Questo comporta allora una serie di
-conseguenze. La più ovvia è che se si cerca di scrivere su una zona mappata in
-sola lettura si avrà l'emissione di un segnale di violazione di accesso
-(\const{SIGSEGV}), dato che i permessi sul segmento di memoria relativo non
-consentono questo tipo di accesso.
-
-\begin{figure}[!htb]
-  \centering
-  \includegraphics[width=10cm]{img/mmap_boundary}
-  \caption{Schema della mappatura in memoria di una sezione di file di
-    dimensioni non corrispondenti al bordo di una pagina.}
-  \label{fig:file_mmap_boundary}
-\end{figure}
+tutto quanto è comunque basato sul meccanismo della \index{memoria~virtuale}
+memoria virtuale. Questo comporta allora una serie di conseguenze. La più
+ovvia è che se si cerca di scrivere su una zona mappata in sola lettura si
+avrà l'emissione di un segnale di violazione di accesso (\const{SIGSEGV}),
+dato che i permessi sul segmento di memoria relativo non consentono questo
+tipo di accesso.
 
 È invece assai diversa la questione relativa agli accessi al di fuori della
 regione di cui si è richiesta la mappatura. A prima vista infatti si potrebbe
 ritenere che anch'essi debbano generare un segnale di violazione di accesso;
 questo però non tiene conto del fatto che, essendo basata sul meccanismo della
-paginazione\index{paginazione}, la mappatura in memoria non può che essere
+paginazione \index{paginazione}, la mappatura in memoria non può che essere
 eseguita su un segmento di dimensioni rigorosamente multiple di quelle di una
 pagina, ed in generale queste potranno non corrispondere alle dimensioni
-effettive del file o della sezione che si vuole mappare. Il caso più comune è
-quello illustrato in fig.~\ref{fig:file_mmap_boundary}, in cui la sezione di
-file non rientra nei confini di una pagina: in tal caso verrà il file sarà
-mappato su un segmento di memoria che si estende fino al bordo della pagina
-successiva.
+effettive del file o della sezione che si vuole mappare.
+
+\footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di
+  memoria.}  
+
+\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è stato
+  implementato in Linux a partire dai kernel della serie 2.4.x; esso consente
+  di creare segmenti di memoria condivisa e torneremo sul suo utilizzo in
+  sez.~\ref{sec:ipc_mmap_anonymous}.}
+
+\footnotetext{questo flag ed il precedente \const{MAP\_POPULATE} sono stati
+  introdotti nel kernel 2.5.46 insieme alla mappatura non lineare di cui
+  parleremo più avanti.}
+
+\begin{figure}[!htb] 
+  \centering
+  \includegraphics[width=12cm]{img/mmap_boundary}
+  \caption{Schema della mappatura in memoria di una sezione di file di
+    dimensioni non corrispondenti al bordo di una pagina.}
+  \label{fig:file_mmap_boundary}
+\end{figure}
+
+
+Il caso più comune è quello illustrato in fig.~\ref{fig:file_mmap_boundary},
+in cui la sezione di file non rientra nei confini di una pagina: in tal caso
+verrà il file sarà mappato su un segmento di memoria che si estende fino al
+bordo della pagina successiva.
 
 In questo caso è possibile accedere a quella zona di memoria che eccede le
 dimensioni specificate da \param{lenght}, senza ottenere un \const{SIGSEGV}
@@ -1206,14 +2276,6 @@ file mappato sono pi
 file è stato troncato, dopo che è stato mappato, ad una dimensione inferiore a
 quella della mappatura in memoria.
 
-\begin{figure}[htb]
-  \centering
-  \includegraphics[width=10cm]{img/mmap_exceed}
-  \caption{Schema della mappatura in memoria di file di dimensioni inferiori
-    alla lunghezza richiesta.}
-  \label{fig:file_mmap_exceed}
-\end{figure}
-
 In questa situazione, per la sezione di pagina parzialmente coperta dal
 contenuto del file, vale esattamente quanto visto in precedenza; invece per la
 parte che eccede, fino alle dimensioni date da \param{length}, l'accesso non
@@ -1231,6 +2293,14 @@ sez.~\ref{sec:file_vfs_work}). Si tenga presente per
 di dispositivi (un esempio è l'interfaccia al ponte PCI-VME del chip Universe)
 che sono utilizzabili solo con questa interfaccia.
 
+\begin{figure}[htb]
+  \centering
+  \includegraphics[width=12cm]{img/mmap_exceed}
+  \caption{Schema della mappatura in memoria di file di dimensioni inferiori
+    alla lunghezza richiesta.}
+  \label{fig:file_mmap_exceed}
+\end{figure}
+
 Dato che passando attraverso una \func{fork} lo spazio di indirizzi viene
 copiato integralmente, i file mappati in memoria verranno ereditati in maniera
 trasparente dal processo figlio, mantenendo gli stessi attributi avuti nel
@@ -1252,12 +2322,12 @@ consentita la scrittura sul file (cio
 o in corrispondenza di una eventuale \func{msync}.
 
 Dato per i file mappati in memoria le operazioni di I/O sono gestite
-direttamente dalla memoria virtuale, occorre essere consapevoli delle
-interazioni che possono esserci con operazioni effettuate con l'interfaccia
-standard dei file di cap.~\ref{cha:file_unix_interface}. Il problema è che una
-volta che si è mappato un file, le operazioni di lettura e scrittura saranno
-eseguite sulla memoria, e riportate su disco in maniera autonoma dal sistema
-della memoria virtuale.
+direttamente dalla \index{memoria~virtuale}memoria virtuale, occorre essere
+consapevoli delle interazioni che possono esserci con operazioni effettuate
+con l'interfaccia standard dei file di cap.~\ref{cha:file_unix_interface}. Il
+problema è che una volta che si è mappato un file, le operazioni di lettura e
+scrittura saranno eseguite sulla memoria, e riportate su disco in maniera
+autonoma dal sistema della memoria virtuale.
 
 Pertanto se si modifica un file con l'interfaccia standard queste modifiche
 potranno essere visibili o meno a seconda del momento in cui la memoria
@@ -1282,8 +2352,9 @@ memoria mappata con il file su disco; il suo prototipo 
   \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
     errore nel qual caso \var{errno} assumerà uno dei valori:
     \begin{errlist}
-    \item[\errcode{EINVAL}] O \param{start} non è multiplo di \const{PAGESIZE},
-    o si è specificato un valore non valido per \param{flags}.
+    \item[\errcode{EINVAL}] O \param{start} non è multiplo di
+      \const{PAGE\_SIZE}, o si è specificato un valore non valido per
+      \param{flags}.
     \item[\errcode{EFAULT}] L'intervallo specificato non ricade in una zona
       precedentemente mappata.
     \end{errlist}
@@ -1344,40 +2415,341 @@ mappatura della memoria usando la funzione \funcd{munmap}, il suo prototipo 
   }
 \end{functions}
 
-La funzione cancella la mappatura per l'intervallo specificato attraverso
-\param{start} e \param{length}, ed ogni successivo accesso a tale regione
-causerà un errore di accesso in memoria. L'argomento \param{start} deve essere
-allineato alle dimensioni di una pagina di memoria, e la mappatura di tutte le
-pagine contenute (anche parzialmente) nell'intervallo indicato, verrà rimossa.
-Indicare un intervallo che non contiene pagine mappate non è un errore.
+La funzione cancella la mappatura per l'intervallo specificato con
+\param{start} e \param{length}; ogni successivo accesso a tale regione causerà
+un errore di accesso in memoria. L'argomento \param{start} deve essere
+allineato alle dimensioni di una pagina, e la mappatura di tutte le pagine
+contenute anche parzialmente nell'intervallo indicato, verrà rimossa.
+Indicare un intervallo che non contiene mappature non è un errore.  Si tenga
+presente inoltre che alla conclusione di un processo ogni pagina mappata verrà
+automaticamente rilasciata, mentre la chiusura del file descriptor usato per
+il \textit{memory mapping} non ha alcun effetto su di esso.
+
+Lo standard POSIX prevede anche una funzione che permetta di cambiare le
+protezioni delle pagine di memoria; lo standard prevede che essa si applichi
+solo ai \textit{memory mapping} creati con \func{mmap}, ma nel caso di Linux
+la funzione può essere usata con qualunque pagina valida nella memoria
+virtuale. Questa funzione è \funcd{mprotect} ed il suo prototipo è:
+\begin{functions}  
+%  \headdecl{unistd.h}
+  \headdecl{sys/mman.h} 
+
+  \funcdecl{int mprotect(const void *addr, size\_t len, int prot)}
+  
+  Modifica le protezioni delle pagine di memoria comprese nell'intervallo
+  specificato.
+
+  \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
+    errore nel qual caso \var{errno} assumerà uno dei valori:
+    \begin{errlist}
+    \item[\errcode{EINVAL}] il valore di \param{addr} non è valido o non è un
+      multiplo di \const{PAGE\_SIZE}.
+    \item[\errcode{EACCESS}] l'operazione non è consentita, ad esempio si è
+      cercato di marcare con \const{PROT\_WRITE} un segmento di memoria cui si
+      ha solo accesso in lettura.
+%     \item[\errcode{ENOMEM}] non è stato possibile allocare le risorse
+%       necessarie all'interno del kernel.
+%     \item[\errcode{EFAULT}] si è specificato un indirizzo di memoria non
+%       accessibile.
+    \end{errlist}
+    ed inoltre \errval{ENOMEM} ed \errval{EFAULT}.
+  } 
+\end{functions}
+
+
+La funzione prende come argomenti un indirizzo di partenza in \param{addr},
+allineato alle dimensioni delle pagine di memoria, ed una dimensione
+\param{size}. La nuova protezione deve essere specificata in \param{prot} con
+una combinazione dei valori di tab.~\ref{tab:file_mmap_prot}.  La nuova
+protezione verrà applicata a tutte le pagine contenute, anche parzialmente,
+dall'intervallo fra \param{addr} e \param{addr}+\param{size}-1.
+
+Infine Linux supporta alcune operazioni specifiche non disponibili su altri
+kernel unix-like. La prima di queste è la possibilità di modificare un
+precedente \textit{memory mapping}, ad esempio per espanderlo o restringerlo.
+Questo è realizzato dalla funzione \funcd{mremap}, il cui prototipo è:
+\begin{functions}  
+  \headdecl{unistd.h}
+  \headdecl{sys/mman.h} 
+
+  \funcdecl{void * mremap(void *old\_address, size\_t old\_size , size\_t
+    new\_size, unsigned long flags)}
+  
+  Restringe o allarga una mappatura in memoria di un file.
+
+  \bodydesc{La funzione restituisce l'indirizzo alla nuova area di memoria in
+    caso di successo od il valore \const{MAP\_FAILED} (pari a \texttt{(void *)
+      -1}) in caso di errore, nel qual caso \var{errno} assumerà uno dei
+    valori:
+    \begin{errlist}
+    \item[\errcode{EINVAL}] il valore di \param{old\_address} non è un
+      puntatore valido.
+    \item[\errcode{EFAULT}] ci sono indirizzi non validi nell'intervallo
+      specificato da \param{old\_address} e \param{old\_size}, o ci sono altre
+      mappature di tipo non corrispondente a quella richiesta.
+    \item[\errcode{ENOMEM}] non c'è memoria sufficiente oppure l'area di
+      memoria non può essere espansa all'indirizzo virtuale corrente, e non si
+      è specificato \const{MREMAP\_MAYMOVE} nei flag.
+    \item[\errcode{EAGAIN}] il segmento di memoria scelto è bloccato e non può
+      essere rimappato.
+    \end{errlist}
+  }
+\end{functions}
+
+La funzione richiede come argomenti \param{old\_address} (che deve essere
+allineato alle dimensioni di una pagina di memoria) che specifica il
+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}\footnote{per poter
+  utilizzare questa costante occorre aver definito \macro{\_GNU\_SOURCE} prima
+  di includere \file{sys/mman.h}.}  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 con \param{old\_address}.
+
+La funzione si appoggia al sistema della \index{memoria~virtuale} memoria
+virtuale per modificare l'associazione fra gli indirizzi virtuali del processo
+e le pagine di memoria, modificando i dati direttamente nella
+\itindex{page~table} \textit{page table} del processo. Come per
+\func{mprotect} la funzione può essere usata in generale, anche per pagine di
+memoria non corrispondenti ad un \textit{memory mapping}, e consente così di
+implementare la funzione \func{realloc} in maniera molto efficiente.
+
+Una caratteristica comune a tutti i sistemi unix-like è che la mappatura in
+memoria di un file viene eseguita in maniera lineare, cioè parti successive di
+un file vengono mappate linearmente su indirizzi successivi in memoria.
+Esistono però delle applicazioni\footnote{in particolare la tecnica è usata
+  dai database o dai programmi che realizzano macchine virtuali.} in cui è
+utile poter mappare sezioni diverse di un file su diverse zone di memoria.
+
+Questo è ovviamente sempre possibile eseguendo ripetutamente la funzione
+\func{mmap} per ciascuna delle diverse aree del file che si vogliono mappare
+in sequenza non lineare,\footnote{ed in effetti è quello che veniva fatto
+  anche con Linux prima che fossero introdotte queste estensioni.} ma questo
+approccio ha delle conseguenze molto pesanti in termini di prestazioni.
+Infatti per ciascuna mappatura in memoria deve essere definita nella
+\itindex{page~table} \textit{page table} del processo una nuova area di
+memoria virtuale\footnote{quella che nel gergo del kernel viene chiamata VMA
+  (\textit{virtual memory area}).} che corrisponda alla mappatura, in modo che
+questa diventi visibile nello spazio degli indirizzi come illustrato in
+fig.~\ref{fig:file_mmap_layout}.
+
+Quando un processo esegue un gran numero di mappature diverse\footnote{si può
+  arrivare anche a centinaia di migliaia.} per realizzare a mano una mappatura
+non-lineare si avrà un accrescimento eccessivo della sua \itindex{page~table}
+\textit{page table}, e lo stesso accadrà per tutti gli altri processi che
+utilizzano questa tecnica. In situazioni in cui le applicazioni hanno queste
+esigenze si avranno delle prestazioni ridotte, dato che il kernel dovrà
+impiegare molte risorse\footnote{sia in termini di memoria interna per i dati
+  delle \itindex{page~table} \textit{page table}, che di CPU per il loro
+  aggiornamento.} solo per mantenere i dati di una gran quantità di
+\textit{memory mapping}.
+
+Per questo motivo con il kernel 2.5.46 è stato introdotto, ad opera di Ingo
+Molnar, un meccanismo che consente la mappatura non-lineare. Anche questa è
+una caratteristica specifica di Linux, non presente in altri sistemi
+unix-like.  Diventa così possibile utilizzare una sola mappatura
+iniziale\footnote{e quindi una sola \textit{virtual memory area} nella
+  \itindex{page~table} \textit{page table} del processo.} e poi rimappare a
+piacere all'interno di questa i dati del file. Ciò è possibile grazie ad una
+nuova system call, \funcd{remap\_file\_pages}, il cui prototipo è:
+\begin{functions}  
+  \headdecl{sys/mman.h} 
+
+  \funcdecl{int remap\_file\_pages(void *start, size\_t size, int prot,
+    ssize\_t pgoff, int flags)}
+  
+  Permette di rimappare non linearmente un precedente \textit{memory mapping}.
+
+  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+    \begin{errlist}
+    \item[\errcode{EINVAL}] Si è usato un valore non valido per uno degli
+      argomenti o \param{start} non fa riferimento ad un \textit{memory
+        mapping} valido creato con \const{MAP\_SHARED}.
+    \end{errlist}
+  }
+\end{functions}
+
+Per poter utilizzare questa funzione occorre anzitutto effettuare
+preliminarmente una chiamata a \func{mmap} con \const{MAP\_SHARED} per
+definire l'area di memoria che poi sarà rimappata non linearmente. Poi di
+chiamerà questa funzione per modificare le corrispondenze fra pagine di
+memoria e pagine del file; si tenga presente che \func{remap\_file\_pages}
+permette anche di mappare la stessa pagina di un file in più pagine della
+regione mappata.
+
+La funzione richiede che si identifichi la sezione del file che si vuole
+riposizionare all'interno del \textit{memory mapping} con gli argomenti
+\param{pgoff} e \param{size}; l'argomento \param{start} invece deve indicare
+un indirizzo all'interno dell'area definita dall'\func{mmap} iniziale, a
+partire dal quale la sezione di file indicata verrà rimappata. L'argomento
+\param{prot} deve essere sempre nullo, mentre \param{flags} prende gli stessi
+valori di \func{mmap} (quelli di tab.~\ref{tab:file_mmap_prot}) ma di tutti i
+flag solo \const{MAP\_NONBLOCK} non viene ignorato.
+
+Insieme alla funzione \func{remap\_file\_pages} nel kernel 2.5.46 con sono
+stati introdotti anche due nuovi flag per \func{mmap}: \const{MAP\_POPULATE} e
+\const{MAP\_NONBLOCK}.  Il primo dei due consente di abilitare il meccanismo
+del \itindex{prefaulting} \textit{prefaulting}. Questo viene di nuovo in aiuto
+per migliorare le prestazioni in certe condizioni di utilizzo del
+\textit{memory mapping}. 
+
+Il problema si pone tutte le volte che si vuole mappare in memoria un file di
+grosse dimensioni. Il comportamento normale del sistema della
+\index{memoria~virtuale} memoria virtuale è quello per cui la regione mappata
+viene aggiunta alla \itindex{page~table} \textit{page table} del processo, ma
+i dati verranno effettivamente utilizzati (si avrà cioè un
+\itindex{page~fault} \textit{page fault} che li trasferisce dal disco alla
+memoria) soltanto in corrispondenza dell'accesso a ciascuna delle pagine
+interessate dal \textit{memory mapping}. 
+
+Questo vuol dire che il passaggio dei dati dal disco alla memoria avverrà una
+pagina alla volta con un gran numero di \itindex{page~fault} \textit{page
+  fault}, chiaramente se si sa in anticipo che il file verrà utilizzato
+immediatamente, è molto più efficiente eseguire un \itindex{prefaulting}
+\textit{prefaulting} in cui tutte le pagine di memoria interessate alla
+mappatura vengono ``\textsl{popolate}'' in una sola volta, questo
+comportamento viene abilitato quando si usa con \func{mmap} il flag
+\const{MAP\_POPULATE}.
+
+Dato che l'uso di \const{MAP\_POPULATE} comporta dell'I/O su disco che può
+rallentare l'esecuzione di \func{mmap} è stato introdotto anche un secondo
+flag, \const{MAP\_NONBLOCK}, che esegue un \itindex{prefaulting}
+\textit{prefaulting} più limitato in cui vengono popolate solo le pagine della
+mappatura che già si trovano nella cache del kernel.\footnote{questo può
+  essere utile per il linker dinamico, in particolare quando viene effettuato
+  il \textit{prelink} delle applicazioni.}
+
+\itindend{memory~mapping}
+
+
+\subsection{L'I/O diretto fra file descriptor}
+\label{sec:file_sendfile_splice}
+
+
+Uno dei problemi che si presenta nella gestione dell'I/O è quello in cui si
+devono trasferire grandi quantità di dati da un file descriptor ed un altro;
+questo usualmente comporta la lettura dei dati dal primo file descriptor in un
+buffer in memoria, da cui essi vengono poi scritti sul secondo.
+
+Benché il kernel ottimizzi la gestione di questo processo quando si ha a che
+fare con file normali, in generale quando i dati da trasferire sono molti si
+pone il problema di effettuare trasferimenti di grandi quantità di dati da
+kernel space a user space e all'indietro, quando in realtà sarebbe molto più
+efficiente tenere tutto in kernel space. Tratteremo in questa sezione alcune
+funzioni specialistiche che permettono di ottimizzare le prestazioni in questo
+tipo di situazioni.
+
+La prima funzione che si pone l'obiettivo di ottimizzare il trasferimento dei
+dati fra due file descriptor è \funcd{sendfile}; la funzione è presente in
+diverse versioni di Unix,\footnote{la si ritrova ad esempio in FreeBSD, HPUX
+  ed altri Unix.} ma non è presente né in POSIX.1-2001 né in altri standard,
+per cui vengono utilizzati diversi prototipi e semantiche
+differenti;\footnote{pertanto si eviti di utilizzarla se si devono scrivere
+  programmi portabili.} nel caso di Linux il suo prototipo è:
+\begin{functions}  
+  \headdecl{sys/sendfile.h} 
+
+  \funcdecl{ssize\_t sendfile(int out\_fd, int in\_fd, off\_t *offset, size\_t
+    count)} 
+  
+  Copia dei dati da un file descriptor ad un altro.
+
+  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+    errore, nel qual caso \var{errno} assumerà uno dei valori:
+    \begin{errlist}
+    \item[\errcode{EAGAIN}] si è impostata la modalità non bloccante su
+      \param{out\_fd} e la scrittura si bloccherebbe.
+    \item[\errcode{EINVAL}] i file descriptor non sono validi, o sono bloccati
+      o una operazione di \func{mmap} non è disponibile per \param{in\_fd}.
+    \item[\errcode{EIO}] si è avuto un errore di lettura da \param{in\_fd}.
+    \item[\errcode{ENOMEM}] non c'è memoria sufficiente per la lettura da
+      \param{in\_fd}.
+    \end{errlist}
+    ed inoltre \errcode{EBADF} e \errcode{EFAULT}.
+  }
+\end{functions}
+
+
+%NdA è da finire, sul perché non è abilitata fra file vedi:
+%\href{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}
+%{\texttt{http://www.cs.helsinki.fi/linux/linux-kernel/2001-03/0200.html}}
+
+
+% TODO documentare la funzione sendfile
+% TODO documentare le funzioni tee e splice
+% http://kerneltrap.org/node/6505 e http://lwn.net/Articles/178199/ e 
+% http://lwn.net/Articles/179492/
+% e http://en.wikipedia.org/wiki/Splice_(system_call)
+% e http://kerneltrap.org/node/6505
+
+
+
+
+\subsection{Gestione avanzata dell'accesso ai dati dei file}
+\label{sec:file_fadvise}
+
+Nell'uso generico dell'interfaccia per l'accesso al contenuto dei file le
+operazioni di lettura e scrittura non necessitano di nessun intervento di
+supervisione da parte dei programmi, si eseguirà una \func{read} o una
+\func{write}, i dati verranno passati al kernel che provvederà ad effettuare
+tutte le operazioni (e a gestire il \textit{caching} dei dati) per portarle a
+termine in quello che ritiene essere il modo più efficiente.
+
+Il problema è che il concetto di migliore efficienza impiegato dal kernel è
+relativo all'uso generico, mentre esistono molti casi in cui ci sono esigenze
+specifiche dei singoli programmi, che avendo una conoscenza diretta di come
+verranno usati i file, possono necessitare di effettuare delle ottimizzazioni
+specifiche, relative alle proprie modalità di I/O sugli stessi. Tratteremo in
+questa sezione una serie funzioni che consentono ai programmi di ottimizzare
+il loro accesso ai dati dei file.
+
+
+% TODO documentare \func{madvise}
+% TODO documentare \func{mincore}
+% TODO documentare \func{posix\_fadvise}
+% vedi http://insights.oetiker.ch/linux/fadvise.html
+% questo tread? http://www.ussg.iu.edu/hypermail/linux/kernel/0703.1/0032.html
+% TODO documentare \func{fallocate}
+% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
+
+
+%\subsection{L'utilizzo delle porte di I/O}
+%\label{sec:file_io_port}
+%
+% TODO l'I/O sulle porte di I/O 
+% consultare le manpage di ioperm, iopl e outb
+
 
-Alla conclusione del processo, ogni pagina mappata verrà automaticamente
-rilasciata, mentre la chiusura del file descriptor usato per effettuare la
-mappatura in memoria non ha alcun effetto sulla stessa.
 
 
 \section{Il file locking}
 \label{sec:file_locking}
 
 \index{file!locking|(}
+
 In sez.~\ref{sec:file_sharing} abbiamo preso in esame le modalità in cui un
 sistema unix-like gestisce la condivisione dei 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.
+in \itindex{append~mode} \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 race condition\index{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.
+Questo causa la possibilità di una \itindex{race~condition} \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 race condition\index{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 scrittura.
+evitare le \textit{race condition} \itindex{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 scrittura.
 
 
 
@@ -1388,7 +2760,7 @@ La prima modalit
 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{discretionary file
+  \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
@@ -1536,7 +2908,7 @@ anche se richiesto attraverso un file descriptor, agisce sempre su un file;
 perciò le informazioni relative agli eventuali \textit{file lock} sono
 mantenute a livello di inode\index{inode},\footnote{in particolare, come
   accennato in fig.~\ref{fig:file_flock_struct}, i \textit{file lock} sono
-  mantenuti un una \textit{linked list}\index{linked list} di strutture
+  mantenuti in una \itindex{linked~list} \textit{linked list} di strutture
   \struct{file\_lock}. La lista è referenziata dall'indirizzo di partenza
   mantenuto dal campo \var{i\_flock} della struttura \struct{inode} (per le
   definizioni esatte si faccia riferimento al file \file{fs.h} nei sorgenti
@@ -1562,38 +2934,42 @@ 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\footnote{il puntatore è mantenuto
   nel campo \var{fl\_file} di \struct{file\_lock}, e viene utilizzato solo per
-  i lock creati con la semantica BSD.} alla voce nella \textit{file table} da
-cui si è richiesto il lock, che così ne identifica il titolare.
+  i lock creati con la semantica BSD.} alla voce nella \itindex{file~table}
+\textit{file table} da cui si è richiesto il lock, che così ne identifica il
+titolare.
 
 Questa struttura prevede che, quando si richiede la rimozione di un file lock,
 il kernel acconsenta solo se la richiesta proviene da un file descriptor che
-fa riferimento ad una voce nella file table corrispondente a quella registrata
-nel lock.  Allora se ricordiamo quanto visto in sez.~\ref{sec:file_dup} e
-sez.~\ref{sec:file_sharing}, e cioè che i file descriptor duplicati e quelli
-ereditati in un processo figlio puntano sempre alla stessa voce nella file
-table, si può capire immediatamente quali sono le conseguenze nei confronti
-delle funzioni \func{dup} e \func{fork}.
+fa riferimento ad una voce nella \itindex{file~table} \textit{file table}
+corrispondente a quella registrata nel lock.  Allora se ricordiamo quanto
+visto in sez.~\ref{sec:file_dup} e sez.~\ref{sec:file_sharing}, e cioè che i
+file descriptor duplicati e quelli ereditati in un processo figlio puntano
+sempre alla stessa voce nella \itindex{file~table} \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 file lock attraverso uno qualunque dei file
-descriptor che fanno riferimento alla stessa voce nella 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 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 file lock, la rimozione avrà
-effetto su tutti i file descriptor che condividono la stessa voce nella file
-table, e quindi, nel caso di file descriptor ereditati attraverso una
-\func{fork}, anche su processi diversi.
+descriptor che fanno riferimento alla stessa voce nella \itindex{file~table}
+\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
+  \itindex{file~table} \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 file lock, la rimozione avrà effetto su
+tutti i file descriptor che condividono la stessa voce nella
+\itindex{file~table} \textit{file table}, e quindi, nel caso di file
+descriptor ereditati attraverso una \func{fork}, anche su processi diversi.
 
 Infine, per evitare che la terminazione imprevista di un processo lasci attivi
 dei file lock, quando un file viene chiuso il kernel provveda anche a
 rimuovere tutti i lock 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 lock rimosso) fintanto
-che non viene rilasciata la relativa voce nella 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 lock non viene rilasciato.
+che non viene rilasciata la relativa voce nella \itindex{file~table}
+\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 lock non viene rilasciato.
 
 Si tenga presente infine che \func{flock} non è in grado di funzionare per i
 file mantenuti su NFS, in questo caso, se si ha la necessità di eseguire il
@@ -1625,7 +3001,7 @@ essa viene usata solo secondo il prototipo:
     \item[\errcode{EDEADLK}] Si è richiesto un lock su una regione bloccata da
       un altro processo che è a sua volta in attesa dello sblocco di un lock
       mantenuto dal processo corrente; si avrebbe pertanto un
-      \textit{deadlock}\index{deadlock}. Non è garantito che il sistema
+      \itindex{deadlock} \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 lock.
@@ -1745,7 +3121,7 @@ stato effettivamente acquisito.
 
 \begin{figure}[htb]
   \centering \includegraphics[width=9cm]{img/file_lock_dead}
-  \caption{Schema di una situazione di \textit{deadlock}\index{deadlock}.}
+  \caption{Schema di una situazione di \itindex{deadlock} \textit{deadlock}.}
   \label{fig:file_flock_dead}
 \end{figure}
 
@@ -1757,11 +3133,12 @@ un lock sulla regione 2 che non pu
 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}\index{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 lock che porterebbe ad un \textit{deadlock}.
+porta ad un \itindex{deadlock} \textit{deadlock}, dato che a quel punto anche
+il processo 2 si bloccherebbe, e niente potrebbe sbloccare l'altro processo.
+Per questo motivo il kernel si incarica di rilevare situazioni di questo tipo,
+ed impedirle restituendo un errore di \errcode{EDEADLK} alla funzione che
+cerca di acquisire un lock che porterebbe ad un \itindex{deadlock}
+\textit{deadlock}.
 
 \begin{figure}[!bht]
   \centering \includegraphics[width=13cm]{img/file_posix_lock}
@@ -1783,17 +3160,19 @@ di fig.~\ref{fig:file_flock_struct}:\footnote{in questo caso nella figura si
   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 lock è sempre associato all'inode\index{inode}, solo che in
+  usato.} il lock è sempre associato \index{inode} all'inode, solo che in
 questo caso la titolarità non viene identificata con il riferimento ad una
-voce nella file table, ma con il valore del \acr{pid} del processo.
+voce nella \itindex{file~table} \textit{file table}, ma con il valore del
+\acr{pid} del processo.
 
 Quando si richiede un lock il kernel effettua una scansione di tutti i lock
-presenti sul file\footnote{scandisce cioè la linked list delle strutture
-  \struct{file\_lock}, scartando automaticamente quelle per cui
-  \var{fl\_flags} non è \const{FL\_POSIX}, così che le due interfacce restano
-  ben separate.}  per verificare se la regione richiesta non si sovrappone ad
-una già bloccata, in caso affermativo decide in base al tipo di lock, in caso
-negativo il nuovo lock viene comunque acquisito ed aggiunto alla lista.
+presenti sul file\footnote{scandisce cioè la \itindex{linked~list}
+  \textit{linked list} delle strutture \struct{file\_lock}, scartando
+  automaticamente quelle per cui \var{fl\_flags} non è \const{FL\_POSIX}, così
+  che le due interfacce restano ben separate.}  per verificare se la regione
+richiesta non si sovrappone ad una già bloccata, in caso affermativo decide in
+base al tipo di lock, in caso negativo il nuovo lock viene comunque acquisito
+ed aggiunto alla lista.
 
 Nel caso di rimozione invece questa viene effettuata controllando che il
 \acr{pid} del processo richiedente corrisponda a quello contenuto nel lock.
@@ -1816,7 +3195,7 @@ lock 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 lock viene eseguito sulla base del
-\acr{pid} del processo, possiamo anche prendere in considerazione un'altro
+\acr{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 lock su regioni che si sovrappongono fra loro all'interno
 stesso processo. Siccome il controllo, come nel caso della rimozione, si basa
@@ -1872,7 +3251,7 @@ POSIX), e la variabile \var{cmd} che specifica la modalit
 lock (bloccante o meno), a seconda dell'opzione \cmd{-b}.
 
 Il programma inizia col controllare (\texttt{\small 11--14}) che venga passato
-un parametro (il file da bloccare), che sia stato scelto (\texttt{\small
+un argomento (il file da bloccare), che sia stato scelto (\texttt{\small
   15--18}) il tipo di lock, 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
@@ -2081,7 +3460,7 @@ tab.~\ref{tab:file_lockf_type}.
     \const{LOCK\_SH}& Richiede uno \textit{shared lock}. Più processi possono
                       mantenere un lock condiviso sullo stesso file.\\
     \const{LOCK\_EX}& Richiede un \textit{exclusive lock}. Un solo processo
-                      alla volta può mantenere un lock esclusivo su un file. \\
+                      alla volta può mantenere un lock esclusivo su un file.\\
     \const{LOCK\_UN}& Sblocca il file.\\
     \const{LOCK\_NB}& Non blocca la funzione quando il lock non è disponibile,
                       si specifica sempre insieme ad una delle altre operazioni
@@ -2103,6 +3482,8 @@ affatto equivalente a \func{flock}).
 \subsection{Il \textit{mandatory locking}}
 \label{sec:file_mand_locking}
 
+\itindbeg{mandatory~locking|(}
+
 Il \textit{mandatory locking} è una opzione introdotta inizialmente in SVr4,
 per introdurre un file locking che, come dice il nome, fosse effettivo
 indipendentemente dai controlli eseguiti da un processo. Con il
@@ -2111,32 +3492,34 @@ direttamente al sistema, cos
 opportune verifiche nei processi, questo verrebbe comunque rispettato.
 
 Per poter utilizzare il \textit{mandatory locking} è stato introdotto un
-utilizzo particolare del bit \acr{sgid}. Se si ricorda quanto esposto in
-sez.~\ref{sec:file_suid_sgid}), esso viene di norma utilizzato per cambiare il
-group-ID 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
+utilizzo particolare del bit \itindex{sgid~bit} \acr{sgid}. Se si ricorda
+quanto esposto in sez.~\ref{sec:file_special_perm}), esso viene di norma
+utilizzato per cambiare il group-ID 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_chmod} 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}.}
+  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 root può passare sopra ad un 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 lock. Per questo motivo l'abilitazione del
-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 tab.~\ref{tab:sys_mount_flags}, o con l'opzione
-\cmd{mand} per il comando).
+neanche l'amministratore può passare sopra ad un lock; pertanto un processo
+che blocchi un file cruciale può renderlo completamente inaccessibile,
+rendendo completamente inutilizzabile il sistema\footnote{il problema si
+  potrebbe risolvere rimuovendo il bit \itindex{sgid~bit} \acr{sgid}, ma non è
+  detto che sia così facile fare questa operazione con un sistema bloccato.}
+inoltre con il \textit{mandatory locking} si può bloccare completamente un
+server NFS richiedendo una lettura su un file su cui è attivo un lock. Per
+questo motivo l'abilitazione del 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
+tab.~\ref{tab:sys_mount_flags}, 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
@@ -2187,12 +3570,57 @@ implementativa\footnote{per i dettagli si possono leggere le note relative
 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.
-\index{file!locking|)}
 
+\index{file!locking|)}
 
+\itindend{mandatory~locking|(}
+
+
+% LocalWords:  dell'I locking multiplexing cap dell' sez system call socket BSD
+% LocalWords:  descriptor client deadlock NONBLOCK EAGAIN polling select kernel
+% LocalWords:  pselect like sys unistd int fd readfds writefds exceptfds struct
+% LocalWords:  timeval errno EBADF EINTR EINVAL ENOMEM sleep tab signal void of
+% LocalWords:  CLR ISSET SETSIZE POSIX read NULL nell'header l'header glibc fig
+% LocalWords:  libc header psignal sigmask SOURCE XOPEN timespec sigset race DN
+% LocalWords:  condition sigprocmask tut self trick oldmask poll XPG pollfd l'I
+% LocalWords:  ufds unsigned nfds RLIMIT NOFILE EFAULT ndfs events revents hung
+% LocalWords:  POLLIN POLLRDNORM POLLRDBAND POLLPRI POLLOUT POLLWRNORM POLLERR
+% LocalWords:  POLLWRBAND POLLHUP POLLNVAL POLLMSG SysV stream ASYNC SETOWN FAQ
+% LocalWords:  GETOWN fcntl SETFL SIGIO SETSIG Stevens driven siginfo sigaction
+% LocalWords:  all'I nell'I Frequently Unanswered Question SIGHUP lease holder
+% LocalWords:  breaker truncate write SETLEASE arg RDLCK WRLCK UNLCK GETLEASE
+% LocalWords:  uid capabilities capability EWOULDBLOCK notify dall'OR ACCESS st
+% LocalWords:  pread readv MODIFY pwrite writev ftruncate creat mknod mkdir buf
+% LocalWords:  symlink rename DELETE unlink rmdir ATTRIB chown chmod utime lio
+% LocalWords:  MULTISHOT thread linkando librt layer aiocb asyncronous control
+% LocalWords:  block ASYNCHRONOUS lseek fildes nbytes reqprio PRIORITIZED sigev
+% LocalWords:  PRIORITY SCHEDULING opcode listio sigevent signo value function
+% LocalWords:  aiocbp ENOSYS append error const EINPROGRESS fsync return ssize
+% LocalWords:  DSYNC fdatasync SYNC cancel ECANCELED ALLDONE CANCELED suspend
+% LocalWords:  NOTCANCELED list nent timout sig NOP WAIT NOWAIT size count iov
+% LocalWords:  iovec vector EOPNOTSUPP EISDIR len memory mapping mapped swap NB
+% LocalWords:  mmap length prot flags off MAP FAILED ANONYMOUS EACCES SHARED SH
+% LocalWords:  only ETXTBSY DENYWRITE ENODEV filesystem EPERM EXEC noexec table
+% LocalWords:  ENFILE lenght segment violation SIGSEGV FIXED msync munmap copy
+% LocalWords:  DoS Denial Service EXECUTABLE NORESERVE LOCKED swapping stack fs
+% LocalWords:  GROWSDOWN ANON GiB POPULATE prefaulting SIGBUS fifo VME fork old
+% LocalWords:  exec atime ctime mtime mprotect addr EACCESS mremap address new
+% LocalWords:  long MAYMOVE realloc VMA virtual Ingo Molnar remap pages pgoff
+% LocalWords:  dall' fault cache linker prelink advisory discrectionary lock fl
+% LocalWords:  flock shared exclusive operation dup inode linked NFS cmd ENOLCK
+% LocalWords:  EDEADLK whence SEEK CUR type pid GETLK SETLK SETLKW all'inode HP
+% LocalWords:  switch bsd lockf mandatory SVr sgid group root mount mand TRUNC
+% LocalWords:  SVID UX Documentation sendfile dnotify inotify NdA ppoll fds add
+% LocalWords:  init EMFILE FIONREAD ioctl watch char pathname uint mask ENOSPC
+% LocalWords:  dell'inode CLOSE NOWRITE MOVE MOVED FROM TO rm wd event page ctl
+% LocalWords:  attribute Universe epoll Solaris kqueue level triggered Jonathan
+% LocalWords:  Lemon BSDCON edge Libenzi kevent backporting epfd EEXIST ENOENT
+% LocalWords:  MOD wait EPOLLIN EPOLLOUT EPOLLRDHUP SOCK EPOLLPRI EPOLLERR one
+% LocalWords:  EPOLLHUP EPOLLET EPOLLONESHOT shot maxevents ctlv ALL DONT HPUX
 
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
+% LocalWords:  FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching