Fatto un programma di esempio per inotify senza tirare in mezzo epoll,
[gapil.git] / fileadv.tex
index 6c2bfccc4cb177bc1309572285b2c380b871e32b..67887c80e9eebed448e62ec16837a22ba1e8c491 100644 (file)
@@ -1461,7 +1461,7 @@ sottodirectory; se si vogliono osservare anche questi sar
 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
+singola;\footnote{questa funzionalità però è disponibile soltanto a partire dal
   kernel 2.6.16.} una volta verificatosi uno qualunque fra gli eventi
 richiesti con \func{inotify\_add\_watch} l'\textsl{osservatore} verrà
 automaticamente rimosso dalla lista di osservazione e nessun ulteriore evento
@@ -1504,7 +1504,6 @@ viene cancellato o un filesystem viene smontato i relativi osservatori vengono
 rimossi automaticamente e non è necessario utilizzare
 \func{inotify\_rm\_watch}.
 
-
 Come accennato l'interfaccia di \textit{inotify} prevede che gli eventi siano
 notificati come dati presenti in lettura sul file descriptor associato alla
 coda di notifica. Una applicazione pertanto dovrà leggere i dati da detto file
@@ -1544,7 +1543,7 @@ osservatore 
 maschera di bit che identifica il tipo di evento verificatosi; in essa
 compariranno sia i bit elencati nella prima parte di
 tab.~\ref{tab:inotify_event_watch}, che gli eventuali valori
-aggiuntivi\footnote{questi compaiono solo nel campo \var{maks} di
+aggiuntivi\footnote{questi compaiono solo nel campo \var{mask} di
   \struct{inotify\_event}, e  non utilizzabili in fase di registrazione
   dell'osservatore.} di tab.~\ref{tab:inotify_read_event_flag}.
 
@@ -1598,15 +1597,137 @@ osservazione, in tal caso essi contengono rispettivamente il nome del file
 byte. Il campo \var{name} viene sempre restituito come stringa terminata da
 NUL, con uno o più zeri di terminazione, a seconda di eventuali necessità di
 allineamento del risultato, ed il valore di \var{len} corrisponde al totale
-della dimensione di \var{name}, zeri aggiuntivi compresi. Questo significa che
-le dimensioni di ciascun evento di \textit{inotify} saranno pari al valore
-\code{sizeof(\struct{inotify\_event}) + len}.
+della dimensione di \var{name}, zeri aggiuntivi compresi. La stringa con il
+nome del file viene restituita nella lettura subito dopo la struttura
+\struct{inotify\_event}; questo significa che le dimensioni di ciascun evento
+di \textit{inotify} saranno pari a \code{sizeof(\struct{inotify\_event}) +
+  len}.
 
 Vediamo allora un esempio dell'uso dell'interfaccia di \textit{inotify} con un
-semplice programma che permette di mettere sotto osservazione un file o una
-directory. 
+semplice programma che permette di mettere sotto osservazione uno o più file e
+directory. Il programma si chiama \texttt{inotify\_monitor.c} ed il codice
+completo è disponibile coi sorgenti allegati alla guida, il corpo principale
+del programma, che non contiene la sezione di gestione delle opzioni e le
+funzioni di ausilio è riportato in fig.~\ref{fig:inotify_monitor_example}.
 
+\begin{figure}[!htbp]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/inotify_monitor.c}
+  \end{minipage}
+  \normalsize
+  \caption{Esempio di codice che usa l'interfaccia di \textit{inotify}.}
+  \label{fig:inotify_monitor_example}
+\end{figure}
+
+Una volta completata la scansione delle opzioni il corpo principale del
+programma inizia controllando (\texttt{\small 11--15}) che sia rimasto almeno
+un argomento che indichi quale file o directory mettere sotto osservazione (e
+qualora questo non avvenga esce stampando la pagina di aiuto); dopo di che
+passa (\texttt{\small 16--20}) all'inizializzazione di \textit{inotify}
+ottenendo con \func{inotify\_init} il relativo file descriptor (oppure usce in
+caso di errore).
+
+Il passo successivo è aggiungere (\texttt{\small 21--30}) alla coda di
+notifica gli opportuni osservatori per ciascuno dei file o directory indicati
+all'invocazione del comando; questo viene fatto eseguendo un ciclo
+(\texttt{\small 22--29}) fintanto che la variabile \var{i}, inizializzata a
+zero (\texttt{\small 21}) all'inizio del ciclo, è minore del numero totale di
+argomenti rimasti. All'interno del ciclo si invoca (\texttt{\small 23})
+\func{inotify\_add\_watch} per ciascuno degli argomenti, usando la maschera
+degli eventi data dalla variabile \var{mask} (il cui valore viene impostato
+nella scansione delle opzioni), in caso di errore si esce dal programma
+altrimenti si incrementa l'indice (\texttt{\small 29}).
+
+Completa l'inizializzazione di \textit{inotify} inizia il ciclo principale
+(\texttt{\small 32--56}) del programma, nel quale si resta in attesa degli
+eventi che si intendono osservare. Questo viene fatto eseguendo all'inizio del
+ciclo (\texttt{\small 33}) una \func{read} che si bloccherà fintanto che non
+si saranno verificati eventi. 
+
+Dato che l'interfaccia di \textit{inotify} può riportare anche più eventi in
+una sola lettura, si è avuto cura di passare alla \func{read} un buffer di
+dimensioni adeguate, inizializzato in (\texttt{\small 7}) ad un valore di
+approssimativamente 512 eventi.\footnote{si ricordi che la quantità di dati
+  restituita da \textit{inotify} è variabile a causa della diversa lunghezza
+  del nome del file restituito insieme a \struct{inotify\_event}.} In caso di
+errore di lettura (\texttt{\small 35--40}) il programma esce con un messaggio
+di errore (\texttt{\small 37--39}), a meno che non si tratti di una
+interruzione della system call, nel qual caso (\texttt{\small 36}) si ripete la
+lettura.
+
+Se la lettura è andata a buon fine invece si esegue un ciclo (\texttt{\small
+  43--52}) per leggere tutti gli eventi restituiti, al solito si inizializza
+l'indice \var{i} a zero (\texttt{\small 42}) e si ripetono le operazioni
+(\texttt{\small 43}) fintanto che esso non supera il numero di byte restituiti
+in lettura. Per ciascun evento all'interno del ciclo si assegna\footnote{si
+  noti come si sia eseguito un opportuno \textit{casting} del puntatore.} alla
+variabile \var{event} l'indirizzo nel buffer della corrispondente struttura
+\struct{inotify\_event} (\texttt{\small 44}), e poi si stampano il numero di
+\textit{watch descriptor} (\texttt{\small 45}) ed il file a cui questo fa
+riferimento (\texttt{\small 46}), ricavato dagli argomenti passati a riga di
+comando sfruttando il fatto che i \textit{watch descriptor} vengono assegnati
+in ordine progressivo crescente a partire da 1.
+
+Qualora sia presente il riferimento ad un nome di file associato all'evento lo
+si stampa (\texttt{\small 47--49}); si noti come in questo caso si sia
+utilizzato il valore del campo \var{event->len} e non al fatto che
+\var{event->name} riporti o meno un puntatore nullo.\footnote{l'interfaccia
+  infatti, qualora il nome non sia presente, non avvalora il campo
+  \var{event->name}, che si troverà a contenere quello che era precedentemente
+  presente nella rispettiva locazione di memoria, nel caso più comune il
+  puntatore al nome di un file osservato in precedenza.} Si utilizza poi
+(\texttt{\small 50}) la funzione \code{printevent}, che interpreta il valore
+del campo \var{event->mask} per stampare il tipo di eventi
+accaduti.\footnote{per il relativo codice, che non riportiamo in quanto non
+  essenziale alla comprensione dell'esempio, si possono utilizzare direttamente
+  i sorgenti allegati alla guida.} Infine (\texttt{\small 51}) si provvede ad
+aggiornare l'indice \var{i} per farlo puntare all'evento successivo.
+
+Se adesso usiamo il programma per mettere sotto osservazione una directory, e
+da un altro terminale eseguiamo il comando \texttt{ls} otterremo qualcosa del
+tipo di:
+\begin{verbatim}
+piccardi@gethen:~/gapil/sources$ ./inotify_monitor -a /home/piccardi/gapil/
+Watch descriptor 1
+Observed event on /home/piccardi/gapil/
+IN_OPEN, 
+Watch descriptor 1
+Observed event on /home/piccardi/gapil/
+IN_CLOSE_NOWRITE, 
+\end{verbatim}
 
+I lettori più accorti si saranno resi conto che nel ciclo di lettura degli
+eventi appena illustrato non viene trattato il caso particolare in cui la
+funzione \func{read} restituisce in \var{nread} un valore nullo. Lo si è fatto
+perché con \textit{inotify} il ritorno di una \func{read} con un valore nullo
+avviene soltanto, come forma di avviso, quando si sia eseguita la funzione
+specificando un buffer di dimensione insufficiente a contenere anche un solo
+evento. Nel nostro caso le dimensioni erano senz'altro sufficienti, per cui
+tale evenienza non si verificherà mai.
+
+Ci si potrà però chiedere cosa succede se il buffer è sufficiente per un
+evento, ma non per tutti gli eventi verificatisi. Come si potrà notare nel
+codice illustrato in precedenza non si è presa nessuna precauzione per
+verificare che non ci fossero stati troncamenti dei dati. Anche in questo caso
+il comportamento scelto è corretto, perché l'interfaccia di \textit{inotify}
+garantisce automaticamente, anche quando ne sono presenti in numero maggiore,
+di restituire soltanto il numero di eventi che possono rientrare completamente
+nelle dimensioni del buffer specificato.\footnote{si avrà cioè, facendo
+  riferimento sempre al codice di fig.~\ref{fig:inotify_monitor_example}, che
+  \var{read} sarà in genere minore delle dimensioni di \var{buffer} ed uguale
+  soltanto qualora gli eventi corrispondano esattamente alle dimensioni di
+  quest'ultimo.} Se gli eventi sono di più ne saranno restituiti solo quelli
+che entrano interamente nel buffer e gli altri saranno restituiti alla
+successiva chiamata di \func{read}.
+
+Infine un'ultima caratteristica dell'interfaccia di \textit{inotify} è che gli
+eventi restituiti nella lettura formano una sequenza ordinata, è cioè
+garantito che se si esegue uno spostamento di un file gli eventi vengano
+generati nella sequenza corretta. L'interfaccia garantisce anche che se si
+verificano più eventi consecutivi identici (vale a dire con gli stessi valori
+dei campi \var{wd}, \var{mask}, \var{cookie}, e \var{name}) questi vengono
+raggruppati in un solo evento.
 
 % TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
 % TODO e man inotify
@@ -1999,14 +2120,12 @@ l'operazione sia facilmente eseguibile attraverso una serie multipla di
 chiamate, ci sono casi in cui si vuole poter contare sulla atomicità delle
 operazioni.
 
-Per questo motivo BSD 4.2\footnote{Le due funzioni sono riprese da BSD4.4 ed
-  integrate anche dallo standard Unix 98. Fino alle libc5, Linux usava
-  \type{size\_t} come tipo dell'argomento \param{count}, una scelta logica,
-  che però è stata dismessa per restare aderenti allo standard.} ha introdotto
-due nuove system call, \funcd{readv} e \funcd{writev}, che permettono di
-effettuare con una sola chiamata una lettura o una scrittura su una serie di
-buffer (quello che viene chiamato \textsl{I/O vettorizzato}. I relativi
-prototipi sono:
+Per questo motivo su BSD 4.2 sono state introdotte due nuove system call,
+\funcd{readv} e \funcd{writev},\footnote{in Linux le due funzioni sono riprese
+  da BSD4.4, esse sono previste anche dallo standard POSIX.1-2001.}  che
+permettono di effettuare con una sola chiamata una lettura o una scrittura su
+una serie di buffer (quello che viene chiamato \textsl{I/O vettorizzato}. I
+relativi prototipi sono:
 \begin{functions}
   \headdecl{sys/uio.h}
   
@@ -2020,11 +2139,11 @@ prototipi sono:
     assumerà uno dei valori:
   \begin{errlist}
   \item[\errcode{EINVAL}] si è specificato un valore non valido per uno degli
-    argomenti (ad esempio \param{count} è maggiore di \const{MAX\_IOVEC}).
+    argomenti (ad esempio \param{count} è maggiore di \const{IOV\_MAX}).
   \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.
+    non ci sono dati in lettura.
   \item[\errcode{EOPNOTSUPP}] la coda delle richieste è momentaneamente piena.
   \end{errlist}
   ed anche \errval{EISDIR}, \errval{EBADF}, \errval{ENOMEM}, \errval{EFAULT}
@@ -2052,10 +2171,132 @@ essere letti o scritti ed in che quantit
 
 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}.
+è specificata dall'argomento \param{count}.\footnote{fino alle libc5, Linux
+  usava \type{size\_t} come tipo dell'argomento \param{count}, una scelta
+  logica, che però è stata dismessa per restare aderenti allo standard
+  POSIX.1-2001.}  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}.
+
+La standardizzazione delle due funzioni all'interno della revisione
+POSIX.1-2001 prevede anche che sia possibile avere un limite al numero di
+elementi del vettore \param{vector}. Qualora questo sussista, esso deve essere
+indicato dal valore dalla costante \const{IOV\_MAX}, definita come le altre
+costanti analoghe (vedi sez.~\ref{sec:sys_limits}) in \file{limits.h}; lo
+stesso valore deve essere ottenibile in esecuzione tramite la funzione
+\func{sysconf} richiedendo l'argomento \const{\_SC\_IOV\_MAX} (vedi
+sez.~\ref{sec:sys_sysconf}).
+
+Nel caso di Linux il limite di sistema è di 1024, però se si usano le
+\acr{glibc} queste forniscono un \textit{wrapper} per le system call che si
+accorge se una operazione supererà il precedente limite, in tal caso i dati
+verranno letti o scritti con le usuali \func{read} e \func{write} usando un
+buffer di dimensioni sufficienti appositamente allocato e sufficiente a
+contenere tutti i dati indicati da \param{vector}. L'operazione avrà successo
+ma si perderà l'atomicità del trasferimento da e verso la destinazione finale.
+
+
+% TODO verificare cosa succederà a preadv e pwritev o alla nuova niovec
+% vedi http://lwn.net/Articles/164887/
+
+
+\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}, introdotta con il 2.6.23
+% 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
 
 
 \subsection{File mappati in memoria}
@@ -2071,7 +2312,7 @@ file in una sezione dello spazio di indirizzi del processo.
  che lo ha allocato
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=10cm]{img/mmap_layout}
+  \includegraphics[width=12cm]{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}
@@ -2308,7 +2549,7 @@ effettive del file o della sezione che si vuole mappare.
 
 \begin{figure}[!htb] 
   \centering
-  \includegraphics[width=12cm]{img/mmap_boundary}
+  \includegraphics[width=13cm]{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}
@@ -2351,7 +2592,7 @@ che sono utilizzabili solo con questa interfaccia.
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=12cm]{img/mmap_exceed}
+  \includegraphics[width=13cm]{img/mmap_exceed}
   \caption{Schema della mappatura in memoria di file di dimensioni inferiori
     alla lunghezza richiesta.}
   \label{fig:file_mmap_exceed}
@@ -2682,104 +2923,6 @@ mappatura che gi
 \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}, introdotta con il 2.6.23
-% 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
-
-
 
 
 \section{Il file locking}
@@ -3196,13 +3339,6 @@ 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}
-  \caption{Schema dell'architettura del file locking, nel caso particolare  
-    del suo utilizzo secondo l'interfaccia standard POSIX.}
-  \label{fig:file_posix_lock}
-\end{figure}
-
 
 Per capire meglio il funzionamento del file locking in semantica POSIX (che
 differisce alquanto rispetto da quello di BSD, visto
@@ -3221,6 +3357,13 @@ questo caso la titolarit
 voce nella \itindex{file~table} \textit{file table}, ma con il valore del
 \acr{pid} del processo.
 
+\begin{figure}[!bht]
+  \centering \includegraphics[width=13cm]{img/file_posix_lock}
+  \caption{Schema dell'architettura del file locking, nel caso particolare  
+    del suo utilizzo secondo l'interfaccia standard POSIX.}
+  \label{fig:file_posix_lock}
+\end{figure}
+
 Quando si richiede un lock il kernel effettua una scansione di tutti i lock
 presenti sul file\footnote{scandisce cioè la \itindex{linked~list}
   \textit{linked list} delle strutture \struct{file\_lock}, scartando
@@ -3673,7 +3816,9 @@ possibilit
 % 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
-% LocalWords:  FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching
+% LocalWords:  FOLLOW ONESHOT ONLYDIR FreeBSD EIO caching sysctl instances name
+% LocalWords:  watches IGNORED ISDIR OVERFLOW overflow UNMOUNT queued cookie ls
+% LocalWords:  NUL sizeof casting printevent nread
 
 
 %%% Local Variables: