Correzioni varie alle note (uniformate in stile) e trattazione di
[gapil.git] / fileadv.tex
index 9da4c618f0d58531839af6058641e4b933e0afb2..14e10b8af985199c54470814e0862c08685d43b9 100644 (file)
@@ -1301,12 +1301,14 @@ eliminato.\footnote{anzi, una delle capacit
 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}.
+come dati disponibili in lettura, dette funzioni ritorneranno tutte le volte
+che si avrà un evento di notifica. Così, invece di dover utilizzare i
+segnali,\footnote{considerati una pessima scelta dal punto di vista
+  dell'interfaccia utente.} si potrà gestire l'osservazione degli eventi con
+una qualunque delle modalità di \textit{I/O multiplexing} illustrate in
+sez.~\ref{sec:file_multiplexing}. Qualora si voglia cessare l'osservazione,
+sarà sufficiente chiudere il file descriptor e tutte le risorse allocate
+saranno automaticamente rilasciate.
 
 Infine l'interfaccia di \textit{inotify} consente di mettere sotto
 osservazione, oltre che una directory, anche singoli file.  Una volta creata
@@ -1361,7 +1363,7 @@ flag della prima parte.
   \footnotesize
   \begin{tabular}[c]{|l|c|p{10cm}|}
     \hline
-    \textbf{Flag}  & & \textbf{Significato} \\
+    \textbf{Valore}  & & \textbf{Significato} \\
     \hline
     \hline
     \const{IN\_ACCESS}        &$\bullet$& C'è stato accesso al file in
@@ -1380,7 +1382,7 @@ flag della prima parte.
     \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
+    \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
@@ -1391,17 +1393,17 @@ flag della prima parte.
                                           directory sotto osservazione.\\ 
     \const{IN\_OPEN}          &$\bullet$& Un file è stato aperto.\\ 
     \hline    
-    \const{IN\_CLOSE}         & --      & Combinazione di
+    \const{IN\_CLOSE}         &         & Combinazione di
                                           \const{IN\_CLOSE\_WRITE} e
                                           \const{IN\_CLOSE\_NOWRITE}.\\  
-    \const{IN\_MOVE}          & --      & Combinazione di
+    \const{IN\_MOVE}          &         & Combinazione di
                                           \const{IN\_MOVED\_FROM} e
                                           \const{IN\_MOVED\_TO}.\\
-    \const{IN\_ALL\_EVENTS}   & --      & Combinazione di tutti i flag
+    \const{IN\_ALL\_EVENTS}   &         & Combinazione di tutti i flag
                                           possibili.\\
     \hline    
   \end{tabular}
-  \caption{Le costanti che identificano i valori per la maschera binaria
+  \caption{Le costanti che identificano i bit della maschera binaria
     dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano il
     tipo di evento da tenere sotto osservazione.} 
   \label{tab:inotify_event_watch}
@@ -1422,7 +1424,7 @@ contrario dei precedenti non vengono mai impostati nei risultati in uscita.
   \footnotesize
   \begin{tabular}[c]{|l|p{10cm}|}
     \hline
-    \textbf{Flag}  & \textbf{Significato} \\
+    \textbf{Valore}  & \textbf{Significato} \\
     \hline
     \hline
     \const{IN\_DONT\_FOLLOW}& Non dereferenzia \param{pathname} se questo è un
@@ -1438,7 +1440,7 @@ contrario dei precedenti non vengono mai impostati nei risultati in uscita.
                               quelli per i file che contiene.\\ 
     \hline    
   \end{tabular}
-  \caption{Le costanti che identificano i valori per la maschera binaria
+  \caption{Le costanti che identificano i bit della maschera binaria
     dell'argomento \param{mask} di \func{inotify\_add\_watch} che indicano le
     modalità di osservazione.} 
   \label{tab:inotify_add_watch_flag}
@@ -1461,7 +1463,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 +1506,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 +1545,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}.
 
@@ -1553,7 +1554,7 @@ aggiuntivi\footnote{questi compaiono solo nel campo \var{maks} di
   \footnotesize
   \begin{tabular}[c]{|l|p{10cm}|}
     \hline
-    \textbf{Flag}  & \textbf{Significato} \\
+    \textbf{Valore}  & \textbf{Significato} \\
     \hline
     \hline
     \const{IN\_IGNORED}    & L'osservatore è stato rimosso, sia in maniera 
@@ -1573,7 +1574,7 @@ aggiuntivi\footnote{questi compaiono solo nel campo \var{maks} di
                              osservazione è stato smontato.\\
     \hline    
   \end{tabular}
-  \caption{Le costanti che identificano i flag aggiuntivi usati nella maschera
+  \caption{Le costanti che identificano i bit aggiuntivi usati nella maschera
     binaria del campo \var{mask} di \struct{inotify\_event}.} 
   \label{tab:inotify_read_event_flag}
 \end{table}
@@ -1598,18 +1599,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}
 
-% TODO inserire anche inotify, vedi http://www.linuxjournal.com/article/8478
-% TODO e man inotify
+I lettori più accorti si saranno resi conto che nel ciclo di lettura degli
+eventi appena illustrato non viene trattato il caso particolare in cui la
+funzione \func{read} restituisce in \var{nread} un valore nullo. Lo si è fatto
+perché con \textit{inotify} il ritorno di una \func{read} con un valore nullo
+avviene soltanto, come forma di avviso, quando si sia eseguita la funzione
+specificando un buffer di dimensione insufficiente a contenere anche un solo
+evento. Nel nostro caso le dimensioni erano senz'altro sufficienti, per cui
+tale evenienza non si verificherà mai.
+
+Ci si potrà però chiedere cosa succede se il buffer è sufficiente per un
+evento, ma non per tutti gli eventi verificatisi. Come si potrà notare nel
+codice illustrato in precedenza non si è presa nessuna precauzione per
+verificare che non ci fossero stati troncamenti dei dati. Anche in questo caso
+il comportamento scelto è corretto, perché l'interfaccia di \textit{inotify}
+garantisce automaticamente, anche quando ne sono presenti in numero maggiore,
+di restituire soltanto il numero di eventi che possono rientrare completamente
+nelle dimensioni del buffer specificato.\footnote{si avrà cioè, facendo
+  riferimento sempre al codice di fig.~\ref{fig:inotify_monitor_example}, che
+  \var{read} sarà in genere minore delle dimensioni di \var{buffer} ed uguale
+  soltanto qualora gli eventi corrispondano esattamente alle dimensioni di
+  quest'ultimo.} Se gli eventi sono di più saranno restituiti solo quelli che
+entrano interamente nel buffer e gli altri saranno restituiti alla successiva
+chiamata di \func{read}.
+
+Infine un'ultima caratteristica dell'interfaccia di \textit{inotify} è che gli
+eventi restituiti nella lettura formano una sequenza ordinata, è cioè
+garantito che se si esegue uno spostamento di un file gli eventi vengano
+generati nella sequenza corretta. L'interfaccia garantisce anche che se si
+verificano più eventi consecutivi identici (vale a dire con gli stessi valori
+dei campi \var{wd}, \var{mask}, \var{cookie}, e \var{name}) questi vengono
+raggruppati in un solo evento.
 
 \index{file!inotify|)}
 
@@ -1739,11 +1859,11 @@ appena descritta; i rispettivi prototipi sono:
   \bodydesc{Le funzioni restituiscono 0 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{ENOSYS}] La funzione non è implementata.
-  \item[\errcode{EINVAL}] Si è specificato un valore non valido per i campi
+  \item[\errcode{EBADF}] si è specificato un file descriptor sbagliato.
+  \item[\errcode{ENOSYS}] la funzione non è implementata.
+  \item[\errcode{EINVAL}] si è specificato un valore non valido per i campi
     \var{aio\_offset} o \var{aio\_reqprio} di \param{aiocbp}.
-  \item[\errcode{EAGAIN}] La coda delle richieste è momentaneamente piena.
+  \item[\errcode{EAGAIN}] la coda delle richieste è momentaneamente piena.
   \end{errlist}
 }
 \end{functions}
@@ -1910,10 +2030,10 @@ specifica operazione; il suo prototipo 
     completate, e -1 in caso di errore nel qual caso \var{errno} assumerà uno
     dei valori:
     \begin{errlist}
-    \item[\errcode{EAGAIN}] Nessuna operazione è stata completata entro
+    \item[\errcode{EAGAIN}] nessuna operazione è stata completata entro
       \param{timeout}.
-    \item[\errcode{ENOSYS}] La funzione non è implementata.
-    \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+    \item[\errcode{ENOSYS}] la funzione non è implementata.
+    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
     \end{errlist}
   }
 \end{prototype}
@@ -1941,13 +2061,13 @@ lettura o scrittura; 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{EAGAIN}] Nessuna operazione è stata completata entro
+    \item[\errcode{EAGAIN}] nessuna operazione è stata completata entro
       \param{timeout}.
-    \item[\errcode{EINVAL}] Si è passato un valore di \param{mode} non valido
+    \item[\errcode{EINVAL}] si è passato un valore di \param{mode} non valido
       o un numero di operazioni \param{nent} maggiore di
       \const{AIO\_LISTIO\_MAX}.
-    \item[\errcode{ENOSYS}] La funzione non è implementata.
-    \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
+    \item[\errcode{ENOSYS}] la funzione non è implementata.
+    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale.
     \end{errlist}
   }
 \end{prototype}
@@ -1983,79 +2103,8 @@ Oltre alle precedenti modalit
   asincrono}, esistono altre funzioni che implementano delle modalità di
 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} e la funzione
-\func{sendfile}.
-
-
-\subsection{I/O vettorizzato}
-\label{sec:file_multiple_io}
-
-Un caso abbastanza comune è quello in cui ci si trova a dover eseguire una
-serie multipla di operazioni di I/O, come una serie di letture o scritture di
-vari buffer. Un esempio tipico è quando i dati sono strutturati nei campi di
-una struttura ed essi devono essere caricati o salvati su un file.  Benché
-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:
-\begin{functions}
-  \headdecl{sys/uio.h}
-  
-  \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{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.
-  \end{errlist}
-  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}, 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
-  \begin{minipage}[c]{15cm}
-    \includestruct{listati/iovec.h}
-  \end{minipage} 
-  \normalsize 
-  \caption{La struttura \structd{iovec}, usata dalle operazioni di I/O
-    vettorizzato.} 
-  \label{fig:file_iovec}
-\end{figure}
-
-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}.
+sezione allora prenderemo in esame le interfacce per l'\textsl{I/O mappato in
+  memoria}, per l'\textsl{I/O vettorizzato} e altre funzioni di I/O avanzato.
 
 
 \subsection{File mappati in memoria}
@@ -2071,7 +2120,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}
@@ -2128,29 +2177,29 @@ eseguire la mappatura in memoria di un file, 
     in caso di successo, e \const{MAP\_FAILED} (-1) in caso di errore, nel
     qual caso \var{errno} assumerà uno dei valori:
     \begin{errlist}
-    \item[\errcode{EBADF}] Il file descriptor non è valido, e non si è usato
+    \item[\errcode{EBADF}] il file descriptor non è valido, e non si è usato
       \const{MAP\_ANONYMOUS}.
     \item[\errcode{EACCES}] o \param{fd} non si riferisce ad un file regolare,
       o si è usato \const{MAP\_PRIVATE} ma \param{fd} non è aperto in lettura,
       o si è usato \const{MAP\_SHARED} e impostato \const{PROT\_WRITE} ed
       \param{fd} non è aperto in lettura/scrittura, o si è impostato
       \const{PROT\_WRITE} ed \param{fd} è in \textit{append-only}.
-    \item[\errcode{EINVAL}] I valori di \param{start}, \param{length} o
+    \item[\errcode{EINVAL}] i valori di \param{start}, \param{length} o
       \param{offset} non sono validi (o troppo grandi o non allineati sulla
       dimensione delle pagine).
-    \item[\errcode{ETXTBSY}] Si è impostato \const{MAP\_DENYWRITE} ma
+    \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
+    \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
+    \item[\errcode{ENODEV}] il filesystem di \param{fd} non supporta il memory
       mapping.
-    \item[\errcode{EPERM}] L'argomento \param{prot} ha richiesto
+    \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
+    \item[\errcode{ENFILE}] si è superato il limite del sistema sul numero di
       file aperti (vedi sez.~\ref{sec:sys_resource_limit}).
     \end{errlist}
   }
@@ -2181,7 +2230,6 @@ multiplo della dimensione di una pagina di memoria.
   \label{tab:file_mmap_prot}
 \end{table}
 
-
 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
@@ -2191,7 +2239,7 @@ Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux
   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
+riportati in tab.~\ref{tab:file_mmap_prot}; 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,
@@ -2294,10 +2342,10 @@ 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.
 
-\footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di
+\footnotetext[68]{dato che tutti faranno riferimento alle stesse pagine di
   memoria.}  
 
-\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è stato
+\footnotetext[69]{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}.}
@@ -2308,7 +2356,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 +2399,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}
@@ -2408,10 +2456,10 @@ 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
+    \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
+    \item[\errcode{EFAULT}] l'intervallo specificato non ricade in una zona
       precedentemente mappata.
     \end{errlist}
   }
@@ -2438,7 +2486,8 @@ del file aggiornato.
                             siano invalidate.\\
     \hline    
   \end{tabular}
-  \caption{Valori dell'argomento \param{flag} di \func{msync}.}
+  \caption{Le costanti che identificano i bit per la maschera binaria
+    dell'argomento \param{flag} di \func{msync}.}
   \label{tab:file_mmap_rsync}
 \end{table}
 
@@ -2465,7 +2514,7 @@ mappatura della memoria usando la funzione \funcd{munmap}, 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}] L'intervallo specificato non ricade in una zona
+    \item[\errcode{EINVAL}] l'intervallo specificato non ricade in una zona
       precedentemente mappata.
     \end{errlist}
   }
@@ -2622,7 +2671,7 @@ nuova system call, \funcd{remap\_file\_pages}, il cui 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}] Si è usato un valore non valido per uno degli
+    \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}
@@ -2682,11 +2731,102 @@ mappatura che gi
 \itindend{memory~mapping}
 
 
-\subsection{L'I/O diretto fra file descriptor}
-\label{sec:file_sendfile_splice}
 
+\subsection{I/O vettorizzato: \func{readv} e \func{writev}}
+\label{sec:file_multiple_io}
+
+Un caso abbastanza comune è quello in cui ci si trova a dover eseguire una
+serie multipla di operazioni di I/O, come una serie di letture o scritture di
+vari buffer. Un esempio tipico è quando i dati sono strutturati nei campi di
+una struttura ed essi devono essere caricati o salvati su un file.  Benché
+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 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}
+  
+  \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{EINVAL}] si è specificato un valore non valido per uno degli
+    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.
+  \item[\errcode{EOPNOTSUPP}] la coda delle richieste è momentaneamente piena.
+  \end{errlist}
+  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}, 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.
 
-Uno dei problemi che si presenta nella gestione dell'I/O è quello in cui si
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includestruct{listati/iovec.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{iovec}, usata dalle operazioni di I/O
+    vettorizzato.} 
+  \label{fig:file_iovec}
+\end{figure}
+
+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}.\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: \func{sendfile} e \func{splice}}
+\label{sec:file_sendfile_splice}
+
+Uno dei problemi che si presentano 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.
@@ -2694,18 +2834,20 @@ 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.
+kernel space a user space e all'indietro, quando in realtà potrebbe essere più
+efficiente mantenere 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 è:
+dati fra due file descriptor è \funcd{sendfile};\footnote{la funzione è stata
+  introdotta con i kernel della serie 2.2, e disponibile dalle \acr{glibc}
+  2.1.} 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,\footnote{pertanto si eviti di utilizzarla
+  se si devono scrivere programmi portabili.} per cui per essa vengono
+utilizzati prototipi e semantiche differenti; nel caso di Linux il suo
+prototipo è:
 \begin{functions}  
   \headdecl{sys/sendfile.h} 
 
@@ -2714,13 +2856,15 @@ differenti;\footnote{pertanto si eviti di utilizzarla se si devono scrivere
   
   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:
+  \bodydesc{La funzione restituisce il numero di byte trasferiti 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}.
+      (vedi sez.~\ref{sec:file_locking}), o \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}.
@@ -2729,18 +2873,206 @@ differenti;\footnote{pertanto si eviti di utilizzarla se si devono scrivere
   }
 \end{functions}
 
+La funzione copia direttamente \param{count} byte dal file descriptor
+\param{in\_fd} al file descriptor \param{out\_fd}; in caso di successo
+funzione ritorna il numero di byte effettivamente copiati da \param{in\_fd} a
+\param{out\_fd} o $-1$ in caso di errore, come le ordinarie \func{read} e
+\func{write} questo valore può essere inferiore a quanto richiesto con
+\param{count}.
+
+Se il puntatore \param{offset} è nullo la funzione legge i dati a partire
+dalla posizione corrente su \param{in\_fd}, altrimenti verrà usata la
+posizione indicata dal valore puntato da \param{offset}; in questo caso detto
+valore sarà aggiornato, come \textit{value result argument}, per indicare la
+posizione del byte successivo all'ultimo che è stato letto, mentre la
+posizione corrente sul file non sarà modificata. Se invece \param{offset} è
+nullo la posizione corrente sul file sarà aggiornata tenendo conto dei byte
+letti da \param{in\_fd}.
+
+Fino ai kernel della serie 2.4 la funzione è utilizzabile su un qualunque file
+descriptor, e permette di sostituire la invocazione successiva di una
+\func{read} e una \func{write} (e l'allocazione del relativo buffer) con una
+sola chiamata a \funcd{sendfile}. In questo modo si può diminuire il numero di
+chiamate al sistema e risparmiare in trasferimenti di dati da kernel space a
+user space e viceversa.  La massima utilità della funzione si ha comunque per
+il trasferimento di dati da un file su disco ad un socket di
+rete,\footnote{questo è il caso classico del lavoro eseguito da un server web,
+  ed infatti Apache ha una opzione per il supporto esplicito di questa
+  funzione.} dato che in questo caso diventa possibile effettuare il
+trasferimento diretto via DMA dal controller del disco alla scheda di rete,
+senza neanche allocare un buffer nel kernel,\footnote{il meccanismo è detto
+  \textit{zerocopy} in quanto i dati non vengono mai copiati dal kernel, che
+  si limita a programmare solo le operazioni di lettura e scrittura via DMA.}
+ottenendo la massima efficienza possibile senza pesare neanche sul processore.
+
+In seguito però ci si è accorti che, fatta eccezione per il trasferimento
+diretto da file a socket, non sempre \func{sendfile} comportava miglioramenti
+significativi delle prestazioni rispetto all'uso in sequenza di \func{read} e
+\func{write},\footnote{nel caso generico infatti il kernel deve comunque
+  allocare un buffer ed effettuare la copia dei dati, e in tal caso spesso il
+  guadagno ottenibile nel ridurre il numero di chiamate al sistema non
+  compensa le ottimizzazioni che possono essere fatte da una applicazione in
+  user space che ha una conoscenza diretta su come questi sono strutturati.} e
+che anzi in certi casi si potevano avere anche dei peggioramenti.  Questo ha
+portato, per i kernel della serie 2.6,\footnote{per alcune motivazioni di
+  questa scelta si può fare riferimento a quanto illustrato da Linus Torvalds
+  in \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}}.}
+alla decisione di consentire l'uso della funzione soltanto quando il file da
+cui si legge supporta le operazioni di \textit{memory mapping} (vale a dire
+non è un socket) e quello su cui si scrive è un socket; in tutti gli altri
+casi l'uso di \func{sendfile} darà luogo ad un errore di \errcode{EINVAL}.
+
+Nonostante ci possano essere casi in cui \func{sendfile} non migliora le
+prestazioni, le motivazioni addotte non convincono del tutto e resta il dubbio
+se la scelta di disabilitarla sempre per il trasferimento di dati fra file di
+dati sia davvero corretta. Se ci sono peggioramenti di prestazioni infatti si
+può sempre fare ricorso all'uso successivo di, ma lasciare a disposizione la
+funzione consentirebbe se non altro, anche in assenza di guadagni di
+prestazioni, di semplificare la gestione della copia dei dati fra file,
+evitando di dover gestire l'allocazione di un buffer temporaneo per il loro
+trasferimento; inoltre si avrebbe comunque il vantaggio di evitare inutili
+trasferimenti di dati da kernel space a user space e viceversa.
+
+Questo dubbio si può comunque ritenere superato con l'introduzione, avvenuto a
+partire dal kernel 2.6.17, della nuova system call \func{splice}. Lo scopo di
+questa funzione è quello di fornire un meccanismo generico per il
+trasferimento di dati da o verso un file utilizzando un buffer gestito
+internamente dal kernel. Descritta in questi termini \func{splice} sembra
+semplicemente un ``\textsl{dimezzamento}'' di \func{sendfile}.\footnote{nel
+  senso che un trasferimento di dati fra due file con \func{sendfile} non
+  sarebbe altro che la lettura degli stessi su un buffer seguita dalla
+  relativa scrittura, cosa che in questo caso si dovrebbe eseguire con due
+  chiamate a \func{splice}.} In realtà le due system call sono profondamente
+diverse nel loro meccanismo di funzionamento; \func{sendfile} infatti, come
+accennato, non necessita affatto di avere a disposizione un buffer interno,
+perché esegue un trasferimento diretto di dati; questo la rende in generale
+molto più efficiente, ma anche limitata nelle sue applicazioni, dato che
+questo tipo di trasferimento è possibile solo in casi specifici.\footnote{e
+  nel caso di Linux questi sono anche solo quelli in cui essa può essere
+  effettivamente utilizzata.}
+
+Il concetto che sta dietro a \func{splice} invece è diverso,\footnote{in
+  realtà la proposta originale di Larry Mc Voy non differisce poi tanto negli
+  scopi da \func{sendfile}, quello che rende \func{splice} davvero diversa è
+  stata la reinterpretazione che ne è stata fatta nell'implementazione su
+  Linux realizzata da Jens Anxboe, concetti che sono esposti sinteticamente
+  dallo stesso Linus Torvalds in \href{http://kerneltrap.org/node/6505}
+  {\texttt{http://kerneltrap.org/node/6505}}.} si tratta semplicemente di una
+funzione che consente di fare in maniera del tutto generica delle operazioni
+di trasferimento di dati fra un file e un buffer gestito interamente in kernel
+space. In questo caso il cuore della funzione (e delle affini \func{vmsplice}
+e \func{tee}, che tratteremo più avanti) è appunto l'uso di un buffer in
+kernel space, e questo è anche quello che ne ha semplificato l'adozione,
+perché l'infrastruttura per la gestione di un tale buffer è presente fin dagli
+albori di Unix per la realizzazione delle \textit{pipe} (vedi
+sez.~\ref{sec:ipc_unix}). Dal punto di vista concettuale allora \func{splice}
+non è altro che una diversa interfaccia (rispetto alle \textit{pipe}) con cui
+utilizzare in user space l'oggetto ``\textsl{buffer in kernel space}''.
+
+Così se per una \textit{pipe} o una \textit{fifo} il buffer viene utilizzato
+come area di memoria (vedi fig.~\ref{fig:ipc_pipe_singular}) dove appoggiare i
+dati che vengono trasferiti da un capo all'altro della stessa per creare un
+meccanismo di comunicazione fra processi, nel caso di \func{splice} il buffer
+viene usato o come fonte dei dati che saranno scritti su un file, o come
+destinazione dei dati che vengono letti da un file. La funzione \funcd{splice}
+fornisce quindi una interfaccia generica che consente di trasferire dati da un
+buffer ad un file o viceversa; il suo prototipo, accessibile solo dopo aver
+definito la macro \macro{\_GNU\_SOURCE},\footnote{si ricordi che questa
+  funzione non è contemplata da nessuno standard, è presente solo su Linux, e
+  pertanto deve essere evitata se si vogliono scrivere programmi portabili.}
+è il seguente:
+\begin{functions}  
+  \headdecl{fcntl.h} 
+
+  \funcdecl{long splice(int fd\_in, off\_t *off\_in, int fd\_out, off\_t
+    *off\_out, size\_t len, unsigned int flags)}
+  
+  Trasferisce dati da un file verso una pipe o viceversa.
+
+  \bodydesc{La funzione restituisce il numero di byte trasferiti in caso di
+    successo e $-1$ in caso di errore, nel qual caso \var{errno} assumerà uno
+    dei valori:
+    \begin{errlist}
+    \item[\errcode{EBADF}] uno o entrambi fra \param{fd\_in} e \param{fd\_out}
+      non sono file descriptor validi o, rispettivamente, non sono stati
+      aperti in lettura o scrittura.
+    \item[\errcode{EINVAL}] il filesystem su cui si opera non supporta
+      \func{splice}, oppure nessuno dei file descriptor è una pipe, oppure si
+      è dato un valore a \param{off\_in} o \param{off\_out} ma il
+      corrispondente file è un dispositivo che non supporta la funzione
+      \func{seek}.
+    \item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'operazione
+      richiesta.
+    \item[\errcode{ESPIPE}] o \param{off\_in} o \param{off\_out} non sono
+      \const{NULL} ma il corrispondente file descriptor è una \textit{pipe}.
+    \end{errlist}
+  }
+\end{functions}
+
+La funzione esegue un trasferimento di \param{count} byte dal file descriptor
+\param{fd\_in} al file descriptor \param{fd\_out}, uno dei quali deve essere
+una \textit{pipe}; l'altro file descriptor può essere
+qualunque.\footnote{questo significa che può essere, oltre che un file di
+  dati, anche un altra \textit{pipe}, o un socket.}  Come accennato una
+\textit{pipe} non è altro che un buffer in kernel space, per cui a seconda che
+essa sia usata per \param{fd\_in} o \param{fd\_out} si avrà rispettivamente la
+copia dei dati dal buffer al file o viceversa. 
+
+In caso di successo la funzione ritorna il numero di byte trasferiti, che può
+essere, come per le normali funzioni di lettura e scrittura su file, inferiore
+a quelli richiesti; un valore negativo indicherà un errore mentre un valore
+nullo indicherà che non ci sono dati da trasferire (ad esempio si è giunti
+alla fine del file in lettura). Si tenga presente che, a seconda del verso del
+trasferimento dei dati, la funzione si comporta nei confronti del file
+descriptor che fa riferimento al file ordinario, come \func{read} o
+\func{write}, e pertanto potrà anche bloccarsi (a meno che non si sia aperto
+il suddetto file in modalità non bloccante).
+
+I due argomenti \param{off\_in} e \param{off\_out} consentono di specificare,
+come per l'analogo \param{offset} di \func{sendfile}, la posizione all'interno
+del file da cui partire per il trasferimento dei dati. Come per
+\func{sendfile} un valore nullo indica di usare la posizione corrente sul
+file, ed essa sarà aggiornata automaticamente secondo il numero di byte
+trasferiti. Un valore non nullo invece deve essere un puntatore ad una
+variabile intera che indica la posizione da usare; questa verrà aggiornata, al
+ritorno della funzione, al byte successivo all'ultimo byte trasferito.
+Ovviamente soltanto uno di questi due argomenti, e più precisamente quello che
+fa riferimento al file descriptor non associato alla \textit{pipe}, può essere
+specificato come valore non nullo.
+
+Infine l'argomento \param{flag} consente di controllare alcune caratteristiche
+del funzionamento della funzione; il contenuto è una maschera binaria e deve
+essere specificato come OR aritmetico dei valori riportati in
+tab.~\ref{tab:splice_flag}.
+
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{SPLICE\_F\_MOVE}    & .\\
+    \const{SPLICE\_F\_NONBLOCK}& .\\
+    \const{SPLICE\_F\_MORE}    & .\\
+    \const{SPLICE\_F\_GIFT}    & .\\
+    \hline
+  \end{tabular}
+  \caption{Le costanti che identificano i bit della maschera binaria
+    dell'argomento \param{flag} di \func{slice}, \func{vmslice} e \func{tee}.}
+  \label{tab:splice_flag}
+\end{table}
+
 
-%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
 
 
 
@@ -2769,7 +3101,8 @@ il loro accesso ai dati dei file.
 % 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}
+
+% TODO documentare \func{fallocate}, introdotta con il 2.6.23
 % vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
 
 
@@ -2782,6 +3115,7 @@ il loro accesso ai dati dei file.
 
 
 
+
 \section{Il file locking}
 \label{sec:file_locking}
 
@@ -2913,7 +3247,7 @@ rimuovere un \textit{file lock} 
   \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{EWOULDBLOCK}] Il file ha già un blocco attivo, e si è
+    \item[\errcode{EWOULDBLOCK}] il file ha già un blocco attivo, e si è
       specificato \const{LOCK\_NB}.
     \end{errlist}
   }
@@ -3049,17 +3383,17 @@ essa viene usata solo secondo il 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{EACCES}] L'operazione è proibita per la presenza di
+    \item[\errcode{EACCES}] l'operazione è proibita per la presenza di
       \textit{file lock} da parte di altri processi.
-    \item[\errcode{ENOLCK}] Il sistema non ha le risorse per il locking: ci
+    \item[\errcode{ENOLCK}] il sistema non ha le risorse per il locking: ci
       sono troppi segmenti di lock aperti, si è esaurita la tabella dei lock,
       o il protocollo per il locking remoto è fallito.
-    \item[\errcode{EDEADLK}] Si è richiesto un lock su una regione bloccata da
+    \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
       \itindex{deadlock} \textit{deadlock}. Non è garantito che il sistema
       riconosca sempre questa situazione.
-    \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale prima
+    \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale prima
       di poter acquisire un lock.
     \end{errlist}
     ed inoltre \errval{EBADF}, \errval{EFAULT}.
@@ -3196,13 +3530,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 +3548,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
@@ -3491,10 +3825,10 @@ che utilizza la funzione \funcd{lockf}, il cui 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{EWOULDBLOCK}] Non è possibile acquisire il lock, e si è
+    \item[\errcode{EWOULDBLOCK}] non è possibile acquisire il lock, e si è
       selezionato \const{LOCK\_NB}, oppure l'operazione è proibita perché il
       file è mappato in memoria.
-    \item[\errcode{ENOLCK}] Il sistema non ha le risorse per il locking: ci
+    \item[\errcode{ENOLCK}] il sistema non ha le risorse per il locking: ci
       sono troppi segmenti di lock aperti, si è esaurita la tabella dei lock.
     \end{errlist}
     ed inoltre \errval{EBADF}, \errval{EINVAL}.
@@ -3673,7 +4007,10 @@ 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 limits sysconf SC wrapper
+% LocalWords:  splice result argument DMA controller zerocopy Linus
 
 
 %%% Local Variables: