Correzioni varie per splice
[gapil.git] / fileadv.tex
index ab82f62593d035165a39a78d357c98a7af59db26..a61419f2e09cb23cc672998b5de3a8e551b4afc0 100644 (file)
@@ -29,9 +29,9 @@ controllo più dettagliato delle modalità di I/O.
 In sez.~\ref{sec:file_shared_access} abbiamo preso in esame le modalità in cui
 un sistema unix-like gestisce l'accesso concorrente ai file da parte di
 processi diversi. In quell'occasione si è visto come, con l'eccezione dei file
-aperti in \itindex{append~mode} \textit{append mode}, quando più processi
-scrivono contemporaneamente sullo stesso file non è possibile determinare la
-sequenza in cui essi opereranno.
+aperti in \textit{append mode}, quando più processi scrivono
+contemporaneamente sullo stesso file non è possibile determinare la sequenza
+in cui essi opereranno.
 
 Questo causa la possibilità di una \itindex{race~condition} \textit{race
   condition}; in generale le situazioni più comuni sono due: l'interazione fra
@@ -940,7 +940,7 @@ I/O.
 
 Abbiamo visto in sez.~\ref{sec:sig_gen_beha}, affrontando la suddivisione fra
 \textit{fast} e \textit{slow} \textit{system call},\index{system~call~lente}
-che in certi casi le funzioni di I/O eseguite su un file descritor possono
+che in certi casi le funzioni di I/O eseguite su un file descriptor possono
 bloccarsi indefinitamente. Questo non avviene mai per i file normali, per i
 quali le funzioni di lettura e scrittura ritornano sempre subito, ma può
 avvenire per alcuni \index{file!di~dispositivo} file di dispositivo, come ad
@@ -1127,7 +1127,7 @@ funzione invece i \textit{file descriptor set} non vengono modificati anche in
 caso di errore.
 
 Si tenga presente infine che su Linux, in caso di programmazione
-\textit{multithread} se un file descriptor viene chiuso in un altro
+\textit{multi-thread} se un file descriptor viene chiuso in un altro
 \textit{thread} rispetto a quello in cui si sta usando \func{select}, questa
 non subisce nessun effetto. In altre varianti di sistemi unix-like invece
 \func{select} ritorna indicando che il file descriptor è pronto, con
@@ -1227,14 +1227,14 @@ una variabile locale, in modo da mantenere l'aderenza allo standard POSIX che
 richiede che il valore di \param{timeout} non sia modificato. 
 
 Rispetto a \func{select} la nuova funzione prende un argomento
-aggiuntivo \param{sigmask}, un puntatore ad una \index{maschera~dei~segnali}
-maschera di segnali (si veda sez.~\ref{sec:sig_sigmask}).  Nell'esecuzione la
-maschera dei segnali corrente viene sostituita da quella così indicata
-immediatamente prima di eseguire l'attesa, e viene poi ripristinata al ritorno
-della funzione. L'uso di \param{sigmask} è stato introdotto allo scopo di
-prevenire possibili \textit{race condition} \itindex{race~condition} quando
-oltre alla presenza di dati sui file descriptor come nella \func{select}
-ordinaria, ci si deve porre in attesa anche dell'arrivo di un segnale.
+aggiuntivo \param{sigmask}, un puntatore ad una maschera di segnali (si veda
+sez.~\ref{sec:sig_sigmask}).  Nell'esecuzione la maschera dei segnali corrente
+viene sostituita da quella così indicata immediatamente prima di eseguire
+l'attesa, e viene poi ripristinata al ritorno della funzione. L'uso
+di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
+\textit{race condition} \itindex{race~condition} quando oltre alla presenza di
+dati sui file descriptor come nella \func{select} ordinaria, ci si deve porre
+in attesa anche dell'arrivo di un segnale.
 
 Come abbiamo visto in sez.~\ref{sec:sig_example} la tecnica classica per
 rilevare l'arrivo di un segnale è quella di utilizzare il gestore per
@@ -1285,9 +1285,9 @@ Nello sviluppo di System V, invece di utilizzare l'interfaccia di
 \func{select}, che è una estensione tipica di BSD, è stata introdotta una
 interfaccia completamente diversa, basata sulla funzione di sistema
 \funcd{poll},\footnote{la funzione è prevista dallo standard XPG4, ed è stata
-  introdotta in Linux come system call a partire dal kernel 2.1.23 ed inserita
-  nelle \acr{libc} 5.4.28, originariamente l'argomento \param{nfds} era di
-  tipo \ctyp{unsigned int}, la funzione è stata inserita nello standard
+  introdotta in Linux come \textit{system call} a partire dal kernel 2.1.23 ed
+  inserita nelle \acr{libc} 5.4.28, originariamente l'argomento \param{nfds}
+  era di tipo \ctyp{unsigned int}, la funzione è stata inserita nello standard
   POSIX.1-2001 in cui è stato introdotto il tipo nativo \type{nfds\_t}.} il
 cui prototipo è:
 
@@ -1480,12 +1480,11 @@ ed inoltre \errval{EFAULT} e \errval{ENOMEM} nel loro significato generico.
 \end{funcproto}
 
 La funzione ha lo stesso comportamento di \func{poll}, solo che si può
-specificare, con l'argomento \param{sigmask}, il puntatore ad una
-\index{maschera~dei~segnali} 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:
+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
@@ -1499,7 +1498,7 @@ questo comportamento non modificando mai il valore di \param{timeout} anche se
 in questo caso non esiste nessuno standard che richieda questo comportamento.
 
 Infine anche per \func{poll} e \func{ppoll} valgono le considerazioni relative
-alla possibilità di avere delle notificazione spurie della disponibilita di
+alla possibilità di avere delle notificazione spurie della disponibilità di
 accesso ai file descriptor illustrate per \func{select} in
 sez.~\ref{sec:file_select}, che non staremo a ripetere qui.
 
@@ -1629,9 +1628,9 @@ come estensione della precedente (è disponibile solo a partire dal kernel
 di creazione del file descriptor. Al momento l'unico valore legale
 per \param{flags} (a parte lo zero) è \const{EPOLL\_CLOEXEC}, che consente di
 impostare in maniera atomica sul file descriptor il flag di
-\itindex{close-on-exec} \textit{close-on-exec} (si è trattato il significato
-di \const{O\_CLOEXEC} in sez.~\ref{sec:file_open_close}), senza che sia
-necessaria una successiva chiamata a \func{fcntl}.
+\textit{close-on-exec} (si è trattato il significato di \const{O\_CLOEXEC} in
+sez.~\ref{sec:file_open_close}), senza che sia necessaria una successiva
+chiamata a \func{fcntl}.
 
 Una volta ottenuto un file descriptor per \textit{epoll} il passo successivo è
 indicare quali file descriptor mettere sotto osservazione e quali operazioni
@@ -1965,12 +1964,11 @@ Come già per \func{select} e \func{poll} anche per l'interfaccia di
 contemporaneamente.  Valgono le osservazioni fatte in
 sez.~\ref{sec:file_select}, e per poterlo fare di nuovo è necessaria una
 variante della funzione di attesa che consenta di reimpostare all'uscita una
-\index{maschera~dei~segnali} maschera di segnali, analoga alle estensioni
-\func{pselect} e \func{ppoll} che abbiamo visto in precedenza per
-\func{select} e \func{poll}. In questo caso la funzione di sistema si chiama
-\funcd{epoll\_pwait}\footnote{la funzione è stata introdotta a partire dal
-  kernel 2.6.19, ed è come tutta l'interfaccia di \textit{epoll}, specifica di
-  Linux.} ed il suo prototipo è:
+maschera di segnali, analoga alle estensioni \func{pselect} e \func{ppoll} che
+abbiamo visto in precedenza per \func{select} e \func{poll}. In questo caso la
+funzione di sistema si chiama \funcd{epoll\_pwait}\footnote{la funzione è
+  stata introdotta a partire dal kernel 2.6.19, ed è, come tutta l'interfaccia
+  di \textit{epoll}, specifica di Linux.} ed il suo prototipo è:
 
 \begin{funcproto}{
 \fhead{sys/epoll.h}
@@ -1989,10 +1987,10 @@ variante della funzione di attesa che consenta di reimpostare all'uscita una
 \end{funcproto}
 
 La funzione è del tutto analoga \funcd{epoll\_wait}, soltanto che alla sua
-uscita viene ripristinata la \index{maschera~dei~segnali} maschera di segnali
-originale, sostituita durante l'esecuzione da quella impostata con
-l'argomento \param{sigmask}; in sostanza la chiamata a questa funzione è
-equivalente al seguente codice, eseguito però in maniera atomica:
+uscita viene ripristinata la maschera di segnali originale, sostituita durante
+l'esecuzione da quella impostata con l'argomento \param{sigmask}; in sostanza
+la chiamata a questa funzione è equivalente al seguente codice, eseguito però
+in maniera atomica:
 \includecodesnip{listati/epoll_pwait_means.c} 
 
 Si tenga presente che come le precedenti funzioni di \textit{I/O multiplexing}
@@ -2081,8 +2079,8 @@ tramite file descriptor è \funcd{signalfd},\footnote{in realtà quella
   versione, \funcm{signalfd4}, introdotta con il kernel 2.6.27 e che è quella
   che viene sempre usata a partire dalle \acr{glibc} 2.9, che prende un
   argomento aggiuntivo \code{size\_t sizemask} che indica la dimensione della
-  \index{maschera~dei~segnali} maschera dei segnali, il cui valore viene
-  impostato automaticamente dalle \acr{glibc}.}  il cui prototipo è:
+  maschera dei segnali, il cui valore viene impostato automaticamente dalle
+  \acr{glibc}.}  il cui prototipo è:
 
 \begin{funcproto}{
 \fhead{sys/signalfd.h}
@@ -2120,13 +2118,13 @@ con \param{fd}, in caso di errore invece verrà restituito $-1$.
 
 L'elenco dei segnali che si vogliono gestire con \func{signalfd} deve essere
 specificato tramite l'argomento \param{mask}. Questo deve essere passato come
-puntatore ad una \index{maschera~dei~segnali} maschera di segnali creata con
-l'uso delle apposite macro già illustrate in sez.~\ref{sec:sig_sigset}. La
-maschera deve indicare su quali segnali si intende operare con
-\func{signalfd}; l'elenco può essere modificato con una successiva chiamata a
-\func{signalfd}. Dato che \signal{SIGKILL} e \signal{SIGSTOP} non possono
-essere intercettati (e non prevedono neanche la possibilità di un gestore) un
-loro inserimento nella maschera verrà ignorato senza generare errori.
+puntatore ad una maschera di segnali creata con l'uso delle apposite macro già
+illustrate in sez.~\ref{sec:sig_sigset}. La maschera deve indicare su quali
+segnali si intende operare con \func{signalfd}; l'elenco può essere modificato
+con una successiva chiamata a \func{signalfd}. Dato che \signal{SIGKILL} e
+\signal{SIGSTOP} non possono essere intercettati (e non prevedono neanche la
+possibilità di un gestore) un loro inserimento nella maschera verrà ignorato
+senza generare errori.
 
 L'argomento \param{flags} consente di impostare direttamente in fase di
 creazione due flag per il file descriptor analoghi a quelli che si possono
@@ -2285,13 +2283,13 @@ Il primo passo (\texttt{\small 19-20}) è la creazione di un file descriptor
 quello che useremo per il controllo degli altri.  É poi necessario
 disabilitare la ricezione dei segnali (nel caso \signal{SIGINT},
 \signal{SIGQUIT} e \signal{SIGTERM}) per i quali si vuole la notifica tramite
-file descriptor. Per questo prima li si inseriscono (\texttt{\small 22-25})
-in una \index{maschera~dei~segnali} maschera di segnali \texttt{sigmask} che
-useremo con (\texttt{\small 26}) \func{sigprocmask} per disabilitarli.  Con la
-stessa maschera si potrà per passare all'uso (\texttt{\small 28-29}) di
-\func{signalfd} per abilitare la notifica sul file descriptor
-\var{sigfd}. Questo poi (\texttt{\small 30-33}) dovrà essere aggiunto con
-\func{epoll\_ctl} all'elenco di file descriptor controllati con \texttt{epfd}.
+file descriptor. Per questo prima li si inseriscono (\texttt{\small 22-25}) in
+una maschera di segnali \texttt{sigmask} che useremo con (\texttt{\small 26})
+\func{sigprocmask} per disabilitarli.  Con la stessa maschera si potrà per
+passare all'uso (\texttt{\small 28-29}) di \func{signalfd} per abilitare la
+notifica sul file descriptor \var{sigfd}. Questo poi (\texttt{\small 30-33})
+dovrà essere aggiunto con \func{epoll\_ctl} all'elenco di file descriptor
+controllati con \texttt{epfd}.
 
 Occorrerà infine (\texttt{\small 35-38}) creare la \textit{named fifo} se
 questa non esiste ed aprirla per la lettura (\texttt{\small 39-40}); una
@@ -3922,13 +3920,12 @@ 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 \textit{swap}.
+Infatti, dato che l'accesso è fatto direttamente attraverso la 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 \textit{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
@@ -4354,33 +4351,30 @@ 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} 
+virtuale. Questa funzione di sistema è \funcd{mprotect} ed il suo prototipo è:
 
-  \funcdecl{int mprotect(const void *addr, size\_t len, int prot)}
-  
-  Modifica le protezioni delle pagine di memoria comprese nell'intervallo
-  specificato.
+\begin{funcproto}{
+\fhead{sys/mman.h} 
+\fdecl{int mprotect(const void *addr, size\_t len, int prot)}
+\fdesc{Modifica le protezioni delle pagine di memoria.} 
+}
 
-  \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}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori: 
+  \begin{errlist}
     \item[\errcode{EINVAL}] il valore di \param{addr} non è valido o non è un
       multiplo di \const{PAGE\_SIZE}.
     \item[\errcode{EACCES}] 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}
-
+    \item[\errcode{ENOMEM}] non è stato possibile allocare le risorse
+      necessarie all'interno del kernel o si è specificato un indirizzo di
+      memoria non valido del processo o non corrispondente a pagine mappate
+      (negli ultimi due casi prima del kernel 2.4.19 veniva prodotto,
+      erroneamente, \errcode{EFAULT}).
+  \end{errlist}
+}
+\end{funcproto}
 
 La funzione prende come argomenti un indirizzo di partenza in \param{addr},
 allineato alle dimensioni delle pagine di memoria, ed una dimensione
@@ -4390,23 +4384,23 @@ 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} 
+kernel unix-like per poter usare le quali occorre però dichiarare
+\macro{\_GNU\_SOURCE} prima dell'inclusione di \texttt{sys/mman.h}. La prima
+di queste è la possibilità di modificare un precedente \textit{memory
+  mapping}, ad esempio per espanderlo o restringerlo.  Questo è realizzato
+dalla funzione di sistema \funcd{mremap}, il cui prototipo è:
 
-  \funcdecl{void * mremap(void *old\_address, size\_t old\_size , size\_t
+\begin{funcproto}{
+\fhead{sys/mman.h} 
+\fdecl{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.
+\fdesc{Restringe o allarga una mappatura in memoria.} 
+}
 
-  \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}
+{La funzione ritorna l'indirizzo alla nuova area di memoria in caso di
+  successo o il valore \const{MAP\_FAILED} (pari a \texttt{(void *) -1}), 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
@@ -4417,9 +4411,9 @@ Questo è realizzato dalla funzione \funcd{mremap}, il cui prototipo è:
       è specificato \const{MREMAP\_MAYMOVE} nei flag.
     \item[\errcode{EAGAIN}] il segmento di memoria scelto è bloccato e non può
       essere rimappato.
-    \end{errlist}
-  }
-\end{functions}
+  \end{errlist}
+}
+\end{funcproto}
 
 La funzione richiede come argomenti \param{old\_address} (che deve essere
 allineato alle dimensioni di una pagina di memoria) che specifica il
@@ -4427,80 +4421,77 @@ 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 \headfile{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.
+Il solo valore utilizzato è \const{MREMAP\_MAYMOVE} che consente di eseguire
+l'espansione anche quando non è possibile utilizzare il precedente
+indirizzo. Per questo motivo, se si è usato questo flag, la funzione può
+restituire un indirizzo della nuova zona di memoria che non è detto coincida
+con \param{old\_address}.
+
+La funzione si appoggia al sistema della memoria virtuale per modificare
+l'associazione fra gli indirizzi virtuali del processo e le pagine di memoria,
+modificando i dati direttamente nella \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.
+Esistono però delle applicazioni (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}.
+in sequenza non lineare (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 \textit{page table}
+del processo una nuova area di memoria virtuale, 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 (si può arrivare
+anche a centinaia di migliaia) per realizzare a mano una mappatura non-lineare
+esso vedrà un accrescimento eccessivo della sua \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 per
+mantenere i dati relativi al \textit{memory mapping}, sia in termini di
+memoria interna per i dati delle \textit{page table}, che di CPU per il loro
+aggiornamento.
 
 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 \textit{system call}, \funcd{remap\_file\_pages}, il cui prototipo è:
-\begin{functions}  
-  \headdecl{sys/mman.h} 
+unix-like.  Diventa così possibile utilizzare una sola mappatura iniziale, e
+quindi una sola \textit{virtual memory area} nella \textit{page table} del
+processo, e poi rimappare a piacere all'interno di questa i dati del file. Ciò
+è possibile grazie ad una nuova \textit{system call},
+\funcd{remap\_file\_pages}, il cui prototipo è:
 
-  \funcdecl{int remap\_file\_pages(void *start, size\_t size, int prot,
+\begin{funcproto}{
+\fhead{sys/mman.h} 
+\fdecl{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}.
+\fdesc{Rimappa non linearmente un \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}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori: 
+  \begin{errlist}
     \item[\errcode{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}
+  \end{errlist}
+  ed inoltre 
+ nel loro significato generico.}
+\end{funcproto}
 
 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
+definire l'area di memoria che poi sarà rimappata non linearmente. Poi si
 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
@@ -4532,12 +4523,12 @@ 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 \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}.
+pagina alla volta con un gran numero di \textit{page fault}, chiaramente se si
+sa in anticipo che il file verrà utilizzato immediatamente, è molto più
+efficiente eseguire un \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
@@ -4556,52 +4547,63 @@ verranno eseguiti gli accessi ad un file; è ad esempio molto comune per i
 database effettuare accessi ai dati in maniera pressoché casuale, mentre un
 riproduttore audio o video eseguirà per lo più letture sequenziali.
 
+\itindend{memory~mapping}
+
 Per migliorare le prestazioni a seconda di queste modalità di accesso è
 disponibile una apposita funzione, \funcd{madvise},\footnote{tratteremo in
   sez.~\ref{sec:file_fadvise} le funzioni che consentono di ottimizzare
   l'accesso ai file con l'interfaccia classica.} che consente di fornire al
-kernel delle indicazioni su dette modalità, così che possano essere adottate
-le opportune strategie di ottimizzazione. Il suo prototipo è:
-\begin{functions}  
-  \headdecl{sys/mman.h} 
+kernel delle indicazioni su come un processo intende accedere ad un segmento
+di memoria, anche al di là delle mappature dei file, così che possano essere
+adottate le opportune strategie di ottimizzazione. Il suo prototipo è:
 
-  \funcdecl{int madvise(void *start, size\_t length, int advice)}
-  
-  Fornisce indicazioni sull'uso previsto di un \textit{memory mapping}.
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{int madvise(void *start, size\_t length, int advice)}
+\fdesc{Fornisce indicazioni sull'uso previsto di un segmento di memoria.} 
+}
 
-  \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}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual
+  caso \var{errno} assumerà uno dei valori: 
+  \begin{errlist}
     \item[\errcode{EBADF}] la mappatura esiste ma non corrisponde ad un file.
     \item[\errcode{EINVAL}] \param{start} non è allineato alla dimensione di
       una pagina, \param{length} ha un valore negativo, o \param{advice} non è
       un valore valido, o si è richiesto il rilascio (con
-      \const{MADV\_DONTNEED}) di pagine bloccate o condivise.
+      \const{MADV\_DONTNEED}) di pagine bloccate o condivise o si è usato
+      \const{MADV\_MERGEABLE} o \const{MADV\_UNMERGEABLE} ma il kernel non è
+      stato compilato per il relativo supporto.
     \item[\errcode{EIO}] la paginazione richiesta eccederebbe i limiti (vedi
       sez.~\ref{sec:sys_resource_limit}) sulle pagine residenti in memoria del
       processo (solo in caso di \const{MADV\_WILLNEED}).
     \item[\errcode{ENOMEM}] gli indirizzi specificati non sono mappati, o, in
       caso \const{MADV\_WILLNEED}, non c'è sufficiente memoria per soddisfare
       la richiesta.
-    \end{errlist}
-    ed inoltre \errval{EAGAIN} e \errval{ENOSYS}.
-  }
-\end{functions}
+  \end{errlist}
+  ed inoltre \errval{EAGAIN} e \errval{ENOSYS} nel loro significato generico.}
+\end{funcproto}
 
 La sezione di memoria sulla quale si intendono fornire le indicazioni deve
 essere indicata con l'indirizzo iniziale \param{start} e l'estensione
 \param{length}, il valore di \param{start} deve essere allineato,
-mentre \param{length} deve essere un numero positivo.\footnote{la versione di
-  Linux consente anche un valore nullo per \param{length}, inoltre se una
-  parte dell'intervallo non è mappato in memoria l'indicazione viene comunque
-  applicata alle restanti parti, anche se la funzione ritorna un errore di
-  \errval{ENOMEM}.} L'indicazione viene espressa dall'argomento \param{advice}
-che deve essere specificato con uno dei valori\footnote{si tenga presente che
-  gli ultimi tre valori sono specifici di Linux (introdotti a partire dal
-  kernel 2.6.16) e non previsti dallo standard POSIX.1b.} riportati in
-tab.~\ref{tab:madvise_advice_values}.
+mentre \param{length} deve essere un numero positivo; la versione di Linux
+consente anche un valore nullo per \param{length}, inoltre se una parte
+dell'intervallo non è mappato in memoria l'indicazione viene comunque
+applicata alle restanti parti, anche se la funzione ritorna un errore di
+\errval{ENOMEM}.
+
+L'indicazione viene espressa dall'argomento \param{advice} che deve essere
+specificato con uno dei valori riportati in
+tab.~\ref{tab:madvise_advice_values}; si tenga presente che i valori indicati
+nella seconda parte della tabella sono specifici di Linux e non sono previsti
+dallo standard POSIX.1b.
+La funzione non ha, tranne il caso di \const{MADV\_DONTFORK}, nessun effetto
+sul comportamento di un programma, ma può influenzarne le prestazioni fornendo
+al kernel indicazioni sulle esigenze dello stesso, così che sia possibile
+scegliere le opportune strategie per la gestione del \itindex{read-ahead}
+\textit{read-ahead} e del caching dei dati.
 
-\begin{table}[htb]
+\begin{table}[!htb]
   \centering
   \footnotesize
   \begin{tabular}[c]{|l|p{10 cm}|}
@@ -4609,13 +4611,19 @@ tab.~\ref{tab:madvise_advice_values}.
     \textbf{Valore} & \textbf{Significato} \\
     \hline
     \hline
+    \const{MADV\_DONTNEED}& non ci si aspetta nessun accesso nell'immediato
+                            futuro, pertanto le pagine possono essere
+                            liberate dal kernel non appena necessario; l'area
+                            di memoria resterà accessibile, ma un accesso
+                            richiederà che i dati vengano ricaricati dal file
+                            a cui la mappatura fa riferimento.\\
     \const{MADV\_NORMAL}  & nessuna indicazione specifica, questo è il valore
                             di default usato quando non si è chiamato
                             \func{madvise}.\\
     \const{MADV\_RANDOM}  & ci si aspetta un accesso casuale all'area
                             indicata, pertanto l'applicazione di una lettura
                             anticipata con il meccanismo del
-                            \itindex{read-ahead} \textit{read-ahead} (vedi
+                            \textit{read-ahead} (vedi 
                             sez.~\ref{sec:file_fadvise}) è di
                             scarsa utilità e verrà disabilitata.\\
     \const{MADV\_SEQUENTIAL}& ci si aspetta un accesso sequenziale al file,
@@ -4626,40 +4634,64 @@ tab.~\ref{tab:madvise_advice_values}.
     \const{MADV\_WILLNEED}& ci si aspetta un accesso nell'immediato futuro,
                             pertanto l'applicazione del \textit{read-ahead}
                             deve essere incentivata.\\
-    \const{MADV\_DONTNEED}& non ci si aspetta nessun accesso nell'immediato
-                            futuro, pertanto le pagine possono essere
-                            liberate dal kernel non appena necessario; l'area
-                            di memoria resterà accessibile, ma un accesso
-                            richiederà che i dati vengano ricaricati dal file
-                            a cui la mappatura fa riferimento.\\
     \hline
-    \const{MADV\_REMOVE}  & libera un intervallo di pagine di memoria ed il
-                            relativo supporto sottostante; è supportato
-                            soltanto sui filesystem in RAM \textit{tmpfs} e
-                            \textit{shmfs}.\footnotemark\\ 
+    \const{MADV\_DONTDUMP}& esclude da un \textit{core dump} (vedi
+                            sez.~\ref{sec:sig_standard}) le pagine 
+                            specificate, viene usato per evitare di scrivere
+                            su disco dati relativi a zone di memoria che si sa
+                            non essere utili in un \textit{core dump}.\\
+    \const{MADV\_DODUMP}  & rimuove l'effetto della precedente
+                            \const{MADV\_DONTDUMP} (dal kernel 3.4).\\ 
     \const{MADV\_DONTFORK}& impedisce che l'intervallo specificato venga
                             ereditato dal processo figlio dopo una
                             \func{fork}; questo consente di evitare che il
-                            meccanismo del \itindex{copy~on~write}
-                            \textit{copy on write} effettui la rilocazione
-                            delle pagine quando il padre scrive sull'area
-                            di memoria dopo la \func{fork}, cosa che può
-                            causare problemi per l'hardware che esegue
-                            operazioni in DMA su quelle pagine.\\
+                            meccanismo del \textit{copy on write} effettui la
+                            rilocazione delle pagine quando il padre scrive
+                            sull'area di memoria dopo la \func{fork}, cosa che
+                            può causare problemi per l'hardware che esegue
+                            operazioni in DMA su quelle pagine (dal kernel
+                            2.6.16).\\
     \const{MADV\_DOFORK}  & rimuove l'effetto della precedente
-                            \const{MADV\_DONTFORK}.\\ 
-    \const{MADV\_MERGEABLE}& marca la pagina come accorpabile (indicazione
+                            \const{MADV\_DONTFORK} (dal kernel 2.6.16).\\ 
+    \const{MADV\_HUGEPAGE}& abilita il meccanismo delle \textit{Transparent
+                              Huge Page} (vedi sez.~\ref{sec:huge_pages})
+                            sulla regione indicata; se questa è allineata
+                            alle relative dimensioni il kernel alloca
+                            direttamente delle \textit{huge page}; è
+                            utilizzabile solo con mappature anomime private
+                            (dal kernel 2.6.38).\\
+    \const{MADV\_NOHUGEPAGE}& impedisce che la regione indicata venga
+                            collassata in eventuali \textit{huge page} (dal
+                            kernel 2.6.38).\\
+    \const{MADV\_HWPOISON} &opzione ad uso di debug per verificare codice
+                            che debba gestire errori nella gestione della
+                            memoria; richiede una apposita opzione di
+                            compilazione del kernel, privilegi amministrativi
+                            (la capacità \const{CAP\_SYS\_ADMIN}) e provoca
+                            l'emissione di un segnale di \const{SIGBUS} dal
+                            programma chiamante e rimozione della mappatura
+                            (dal kernel 2.6.32).\\
+    \const{MADV\_SOFT\_OFFLINE}&opzione utilizzata per il debug del
+                            codice di verifica degli errori di gestione
+                            memoria, richiede una apposita opzione di
+                            compilazione (dal kernel 2.6.33).\\
+    \const{MADV\_MERGEABLE}& marca la pagina come accorpabile, indicazione
                             principalmente ad uso dei sistemi di
-                            virtualizzazione).\footnotemark\\
-    \hline
+                            virtualizzazione\footnotemark (dal kernel 2.6.32).\\
+    \const{MADV\_REMOVE}  & libera un intervallo di pagine di memoria ed il
+                            relativo supporto sottostante; è supportato
+                            soltanto sui filesystem in RAM \textit{tmpfs} e
+                            \textit{shmfs} se usato su altri tipi di
+                            filesystem causa un errore di \errcode{ENOSYS}
+                            (dal kernel 2.6.16).\\
+    \const{MADV\_UNMERGEABLE}& rimuove l'effetto della precedente
+                            \const{MADV\_MERGEABLE} (dal kernel 2.6.32). \\
+     \hline
   \end{tabular}
   \caption{Valori dell'argomento \param{advice} di \func{madvise}.}
   \label{tab:madvise_advice_values}
 \end{table}
 
-\footnotetext{se usato su altri tipi di filesystem causa un errore di
-  \errcode{ENOSYS}.}
-
 \footnotetext{a partire dal kernel 2.6.32 è stato introdotto un meccanismo che
   identifica pagine di memoria identiche e le accorpa in una unica pagina
   (soggetta al \textit{copy-on-write} per successive modifiche); per evitare
@@ -4669,64 +4701,115 @@ tab.~\ref{tab:madvise_advice_values}.
   la loro occupazione di memoria, ma il meccanismo può essere usato anche in
   altre applicazioni in cui sian presenti numerosi processi che usano gli
   stessi dati; per maggiori dettagli si veda
-  \href{http://kernelnewbies.org/Linux_2_6_32\#head-d3f32e41df508090810388a57efce73f52660ccb}{\texttt{http://kernelnewbies.org/Linux\_2\_6\_32}}.}
+  \href{http://kernelnewbies.org/Linux_2_6_32\#head-d3f32e41df508090810388a57efce73f52660ccb}{\texttt{http://kernelnewbies.org/Linux\_2\_6\_32}}
+  e la documentazione nei sorgenti del kernel
+  (\texttt{Documentation/vm/ksm.txt}).} 
 
-La funzione non ha, tranne il caso di \const{MADV\_DONTFORK}, nessun effetto
-sul comportamento di un programma, ma può influenzarne le prestazioni fornendo
-al kernel indicazioni sulle esigenze dello stesso, così che sia possibile
-scegliere le opportune strategie per la gestione del \itindex{read-ahead}
-\textit{read-ahead} e del caching dei dati. A differenza da quanto specificato
-nello standard POSIX.1b, per il quale l'uso di \func{madvise} è a scopo
-puramente indicativo, Linux considera queste richieste come imperative, per
-cui ritorna un errore qualora non possa soddisfarle.\footnote{questo
-  comportamento differisce da quanto specificato nello standard.}
 
-\itindend{memory~mapping}
+A differenza da quanto specificato nello standard POSIX.1b, per il quale l'uso
+di \func{madvise} è a scopo puramente indicativo, Linux considera queste
+richieste come imperative, per cui ritorna un errore qualora non possa
+soddisfarle; questo comportamento differisce da quanto specificato nello
+standard.
+
+Nello standard POSIX.1-2001 è prevista una ulteriore funzione
+\funcd{posix\_madvise} che su Linux viene reimplementata utilizzando
+\func{madvise}; il suo prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/mman.h}
+\fdecl{int posix\_madvise(void *start, size\_t lenght, int advice)}
+\fdesc{Fornisce indicazioni sull'uso previsto di un segmento di memoria.} 
+}
+
+{La funzione ritorna $0$ in caso di successo ed un valore positivo per un
+  errore, nel qual caso \var{errno} assumerà uno dei valori:
+  \begin{errlist}
+    \item[\errcode{EINVAL}] \param{start} non è allineato alla dimensione di
+      una pagina, \param{length} ha un valore negativo, o \param{advice} non è
+      un valore valido.
+    \item[\errcode{ENOMEM}] gli indirizzi specificati non sono nello spazio di
+      indirizzi del processo.
+  \end{errlist}
+}
+\end{funcproto}
+
+Gli argomenti \param{start} e \param{lenght} hanno lo stesso identico
+significato degli analoghi di \func{madvise}, a cui si rimanda per la loro
+descrizione ma a differenza di quanto indicato dallo standard per questa
+funzione, su Linux un valore nullo di \param{len} è consentito.
+
+\begin{table}[!htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \const{POSIX\_MADV\_DONTNEED}& analogo a \const{MADV\_DONTNEED}.\\
+    \const{POSIX\_MADV\_NORMAL}  & identico a \const{MADV\_NORMAL}.\\
+    \const{POSIX\_MADV\_RANDOM}  & identico a \const{MADV\_RANDOM}.\\
+    \const{POSIX\_MADV\_SEQUENTIAL}& identico a \const{MADV\_SEQUENTIAL}.\\
+    \const{POSIX\_MADV\_WILLNEED}& identico a \const{MADV\_WILLNEED}.\\
+     \hline
+  \end{tabular}
+  \caption{Valori dell'argomento \param{advice} di \func{posix\_madvise}.}
+  \label{tab:posix_madvise_advice_values}
+\end{table}
+
+
+L'argomento \param{advice} invece può assumere solo i valori indicati in
+tab.~\ref{tab:posix_madvise_advice_values}, che riflettono gli analoghi di
+\func{madvise}, con lo stesso effetto per tutti tranne
+\const{POSIX\_MADV\_DONTNEED}.  Infatti a partire dalle \acr{glibc} 2.6
+\const{POSIX\_MADV\_DONTNEED} viene ignorato, in quanto l'uso del
+corrispondente \const{MADV\_DONTNEED} di \func{madvise} ha, per la semantica
+imperativa, l'effetto immediato di far liberare le pagine da parte del kernel,
+che viene considerato distruttivo.
+
 
 
 \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 a \func{read} e \func{write}, ci sono casi in cui si vuole poter
-contare sulla atomicità delle operazioni.
+Una seconda modalità di I/O diversa da quella ordinaria è il cosiddetto
+\textsl{I/O vettorizzato}, che nasce per rispondere al caso abbastanza comune
+in cui ci si trova nell'esigenza di 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 a \func{read}
+e \func{write}, ci sono casi in cui si vuole poter contare sulla atomicità
+delle operazioni di lettura e scrittura rispetto all'esecuzione del programma.
 
 Per questo motivo fino da BSD 4.2 vennero introdotte delle nuove
 \textit{system call} che permettessero di effettuare con una sola chiamata una
-serie di letture o scritture su una serie di buffer, con quello che viene
-normalmente chiamato \textsl{I/O vettorizzato}. Queste funzioni sono
+serie di letture da, o scritture su, una serie di buffer, quello che poi venne
+chiamato \textsl{I/O vettorizzato}. Queste funzioni di sistema sono
 \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.} ed 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{funcproto}{
+\fhead{sys/uio.h}
+\fdecl{int readv(int fd, const struct iovec *vector, int count)}
+\fdecl{int writev(int fd, const struct iovec *vector, int count)}
+\fdesc{Eseguono rispettivamente una lettura o una scrittura vettorizzata.} 
+}
+
+{Le funzioni ritornano il numero di byte letti o scritti in caso di successo e
+  $-1$ per un errore, nel qual caso \var{errno} assumerà uno dei valori:
   \begin{errlist}
-  \item[\errcode{EINVAL}] si è specificato un valore non valido per uno degli
+    \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}
+  più tutti i valori, con lo stesso significato, che possono risultare
+  dalle condizioni di errore di \func{read} e \func{write}.
+ }
+\end{funcproto}
+
 
 Entrambe le funzioni usano una struttura \struct{iovec}, la cui definizione è
 riportata in fig.~\ref{fig:file_iovec}, che definisce dove i dati devono
@@ -4792,29 +4875,24 @@ sez.~\ref{sec:file_read} e \ref{sec:file_write}); le due funzioni sono
   bit dell'argomento \param{offset}, che varia a seconda delle architetture,
   ma queste differenze vengono gestite dalle funzioni di librerie di libreria
   che mantengono l'interfaccia delle analoghe tratte da BSD.}
-\begin{functions}
-  \headdecl{sys/uio.h}
-  
-  \funcdecl{int preadv(int fd, const struct iovec *vector, int count, off\_t
+
+
+\begin{funcproto}{
+\fhead{sys/uio.h}
+\fdecl{int preadv(int fd, const struct iovec *vector, int count, off\_t
     offset)}
-  \funcdecl{int pwritev(int fd, const struct iovec *vector, int count, off\_t
+\fdecl{int pwritev(int fd, const struct iovec *vector, int count, off\_t
     offset)}
+\fdesc{Eseguono una lettura o una scrittura vettorizzata a partire da una data
+  posizione sul file.} 
+}
 
-  Eseguono una lettura o una scrittura vettorizzata a partire da una data
-  posizione sul file.
-  
-  \bodydesc{Le funzioni hanno gli stessi valori di ritorno delle
-    corrispondenti \func{readv} e \func{writev}; anche gli eventuali errori
-    sono gli stessi già visti in precedenza, ma ad essi si possono aggiungere
-    per \var{errno} anche i valori:
-  \begin{errlist}
-  \item[\errcode{EOVERFLOW}] \param{offset} ha un valore che non può essere
-    usato come \type{off\_t}.
-  \item[\errcode{ESPIPE}] \param{fd} è associato ad un socket o una
-    \textit{pipe}.
-  \end{errlist}
+{ Le funzioni hanno gli stessi valori di ritorno delle corrispondenti
+  \func{readv} e \func{writev} ed anche gli eventuali errori sono gli stessi,
+  con in più quelli che si possono ottenere dalle possibili condizioni di
+  errore di \func{lseek}.
 }
-\end{functions}
+\end{funcproto}
 
 Le due funzioni eseguono rispettivamente una lettura o una scrittura
 vettorizzata a partire dalla posizione \param{offset} sul file indicato
@@ -4844,32 +4922,31 @@ 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à 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.
+\textit{kernel space} a \textit{user space} e all'indietro, quando in realtà
+potrebbe essere più efficiente mantenere tutto in \textit{kernel
+  space}. Tratteremo in questa sezione alcune funzioni specialistiche che
+permettono di ottimizzare le prestazioni in questo tipo di situazioni.
 
 La prima funzione che è stata ideata per ottimizzare il trasferimento dei dati
-fra due file descriptor è \func{sendfile};\footnote{la funzione è stata
+fra due file descriptor è \func{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 prototipo
-di \funcd{sendfile} è:
-\begin{functions}  
-  \headdecl{sys/sendfile.h} 
+  2.1.} La funzione è presente in diverse versioni di Unix (la si ritrova ad
+esempio in FreeBSD, HPUX ed altri Unix) ma non è presente né in POSIX.1-2001
+né in altri standard (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 prototipo di \funcd{sendfile} è:
 
-  \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 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}
+\begin{funcproto}{
+\fhead{sys/sendfile.h}
+\fdecl{ssize\_t sendfile(int out\_fd, int in\_fd, off\_t *offset, size\_t
+    count)}
+\fdesc{Copia dei dati da un file descriptor ad un altro.} 
+}
+
+{La funzione ritorna il numero di byte trasferiti in caso di successo e $-1$
+  per un 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
@@ -4878,17 +4955,16 @@ di \funcd{sendfile} è:
     \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}
+  \end{errlist}
+  ed inoltre \errcode{EBADF} e \errcode{EFAULT} nel loro significato
+  generico.}
+\end{funcproto}
 
 La funzione copia direttamente \param{count} byte dal file descriptor
-\param{in\_fd} al file descriptor \param{out\_fd}; in caso di successo
+\param{in\_fd} al file descriptor \param{out\_fd}. In caso di successo la
 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}.
+\param{out\_fd} e come per 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
@@ -4899,38 +4975,38 @@ 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
+Fino ai kernel della serie 2.4 la funzione era utilizzabile su un qualunque
+file descriptor, e permetteva 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
+sola chiamata a \funcd{sendfile}. In questo modo si poteva 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 ottiene
+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.}
+senza neanche allocare un buffer nel kernel (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
+In seguito però ci si accorse 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 \url{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}.
+\func{write}. 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, per cui 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
+  \url{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} da luogo ad un errore di \errcode{EINVAL}.
 
 Nonostante ci possano essere casi in cui \func{sendfile} non migliora le
 prestazioni, resta il dubbio se la scelta di disabilitarla sempre per il
@@ -4938,27 +5014,31 @@ trasferimento fra file di dati sia davvero corretta. Se ci sono peggioramenti
 di prestazioni infatti si può sempre fare ricorso al metodo ordinario, ma
 lasciare a disposizione la funzione consentirebbe se non altro di semplificare
 la gestione della copia dei dati fra file, evitando di dover gestire
-l'allocazione di un buffer temporaneo per il loro trasferimento.
-
-Questo dubbio si può comunque ritenere superato con l'introduzione, avvenuta a
-partire dal kernel 2.6.17, della nuova \textit{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 \textit{system call} sono
-profondamente diverse nel loro meccanismo di funzionamento;\footnote{questo
-  fino al kernel 2.6.23, dove \func{sendfile} è stata reimplementata in
-  termini di \func{splice}, pur mantenendo disponibile la stessa interfaccia
-  verso l'user space.} \func{sendfile} infatti, come accennato, non necessita
-di avere a disposizione un buffer interno, perché esegue un trasferimento
-diretto di dati; questo la rende in generale 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.}
+l'allocazione di un buffer temporaneo per il loro trasferimento. Comunque a
+partire dal kernel 2.6.33 la restrizione su \param{out\_fd} è stata rimossa e
+questo può essere un file qualunque, rimane però quella di non poter usare un
+socket per \param{in\_fd}.
+
+A partire dal kernel 2.6.17 come alternativa a \func{sendfile} è disponibile
+la nuova \textit{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}, 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 \textit{system call} sono profondamente diverse nel loro
+meccanismo di funzionamento;\footnote{questo fino al kernel 2.6.23, dove
+  \func{sendfile} è stata reimplementata in termini di \func{splice}, pur
+  mantenendo disponibile la stessa interfaccia verso l'user space.}
+\func{sendfile} infatti, come accennato, non necessita di avere a disposizione
+un buffer interno, perché esegue un trasferimento diretto di dati; questo la
+rende in generale più efficiente, ma anche limitata nelle sue applicazioni,
+dato che questo tipo di trasferimento è possibile solo in casi specifici che
+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
@@ -4968,40 +5048,39 @@ Il concetto che sta dietro a \func{splice} invece è diverso,\footnote{in
   dallo stesso Linus Torvalds in \url{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
+gestito interamente in \textit{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}''.
+\textit{pipe}) con cui utilizzare in \textit{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
+destinazione dei dati che vengono letti da un file. La funzione fornisce
+quindi una interfaccia generica che consente di trasferire dati da un buffer
+ad un file o viceversa; il prototipo di \funcd{splice}, 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
+\begin{funcproto}{
+\fhead{fcntl.h} 
+\fdecl{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 \textit{pipe} o viceversa.
+\fdesc{Trasferisce dati da un file verso una \textit{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}
+{La funzione ritorna il numero di byte trasferiti in caso di successo e $-1$
+  per un 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.
@@ -5015,18 +5094,19 @@ definito la macro \macro{\_GNU\_SOURCE},\footnote{si ricordi che questa
       richiesta.
     \item[\errcode{ESPIPE}] o \param{off\_in} o \param{off\_out} non sono
       \val{NULL} ma il corrispondente file descriptor è una \textit{pipe}.
-    \end{errlist}
-  }
-\end{functions}
+  \end{errlist}
+}
+\end{funcproto}
+
 
 La funzione esegue un trasferimento di \param{len} 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. 
+una \textit{pipe}; l'altro file descriptor può essere qualunque, 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 \textit{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
@@ -5068,8 +5148,15 @@ descrizioni complete di tutti i valori possibili anche quando, come per
     \hline
     \const{SPLICE\_F\_MOVE}    & Suggerisce al kernel di spostare le pagine
                                  di memoria contenenti i dati invece di
-                                 copiarle;\footnotemark viene usato soltanto
-                                 da \func{splice}.\\ 
+                                 copiarle: per una maggiore efficienza
+                                 \func{splice} usa quando possibile i
+                                 meccanismi della memoria virtuale per
+                                 eseguire i trasferimenti di dati; in maniera
+                                 analoga a \func{mmap}), qualora le pagine non
+                                 possano essere spostate dalla \textit{pipe} o
+                                 il buffer non corrisponda a pagine intere
+                                 esse saranno comunque copiate. Viene usato
+                                 soltanto da \func{splice}.\\ 
     \const{SPLICE\_F\_NONBLOCK}& Richiede di operare in modalità non
                                  bloccante; questo flag influisce solo sulle
                                  operazioni che riguardano l'I/O da e verso la
@@ -5083,13 +5170,24 @@ descrizioni complete di tutti i valori possibili anche quando, come per
                                  ulteriori dati in una \func{splice}
                                  successiva, questo è un suggerimento utile
                                  che viene usato quando \param{fd\_out} è un
-                                 socket.\footnotemark Attualmente viene usato
-                                 solo da \func{splice}, potrà essere
+                                 socket. Questa opzione consente di utilizzare
+                                 delle opzioni di gestione dei socket che
+                                 permettono di ottimizzare le trasmissioni via
+                                 rete (si veda la descrizione di
+                                 \const{TCP\_CORK} in
+                                 sez.~\ref{sec:sock_tcp_udp_options} e quella
+                                 di \const{MSG\_MORE} in
+                                 sez.~\ref{sec:net_sendmsg}).  Attualmente
+                                 viene usato solo da \func{splice}, potrà essere
                                  implementato in futuro anche per
                                  \func{vmsplice} e \func{tee}.\\
     \const{SPLICE\_F\_GIFT}    & Le pagine di memoria utente sono
-                                 ``\textsl{donate}'' al kernel;\footnotemark
-                                 se impostato una seguente \func{splice} che
+                                 ``\textsl{donate}'' al kernel; questo
+                                 significa che la cache delle pagine e i dati
+                                 su disco potranno differire, e che
+                                 l'applicazione non potrà modificare
+                                 quest'area di memoria. 
+                                 Se impostato una seguente \func{splice} che
                                  usa \const{SPLICE\_F\_MOVE} potrà spostare le 
                                  pagine con successo, altrimenti esse dovranno
                                  essere copiate; per usare questa opzione i
@@ -5105,50 +5203,30 @@ descrizioni complete di tutti i valori possibili anche quando, come per
   \label{tab:splice_flag}
 \end{table}
 
-\footnotetext[120]{per una maggiore efficienza \func{splice} usa quando
-  possibile i meccanismi della memoria virtuale per eseguire i trasferimenti
-  di dati (in maniera analoga a \func{mmap}), qualora le pagine non possano
-  essere spostate dalla \textit{pipe} o il buffer non corrisponda a pagine
-  intere esse saranno comunque copiate.}
-
-\footnotetext[121]{questa opzione consente di utilizzare delle opzioni di
-  gestione dei socket che permettono di ottimizzare le trasmissioni via rete,
-  si veda la descrizione di \const{TCP\_CORK} in
-  sez.~\ref{sec:sock_tcp_udp_options} e quella di \const{MSG\_MORE} in
-  sez.~\ref{sec:net_sendmsg}.}
-
-\footnotetext{questo significa che la cache delle pagine e i dati su disco
-  potranno differire, e che l'applicazione non potrà modificare quest'area di
-  memoria.}
 
 Per capire meglio il funzionamento di \func{splice} vediamo un esempio con un
 semplice programma che usa questa funzione per effettuare la copia di un file
-su un altro senza utilizzare buffer in user space. Il programma si chiama
-\texttt{splicecp.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:splice_example}.
-
-Lo scopo del programma è quello di eseguire la copia dei con \func{splice},
-questo significa che si dovrà usare la funzione due volte, prima per leggere i
-dati e poi per scriverli, appoggiandosi ad un buffer in kernel space (vale a
-dire ad una \textit{pipe}); lo schema del flusso dei dati è illustrato in
-fig.~\ref{fig:splicecp_data_flux}. 
+su un altro senza utilizzare buffer in user space. Lo scopo del programma è
+quello di eseguire la copia dei dati con \func{splice}, questo significa che
+si dovrà usare la funzione due volte, prima per leggere i dati dal file di
+ingresso e poi per scriverli su quello di uscita, appoggiandosi ad una
+\textit{pipe}: lo schema del flusso dei dati è illustrato in
+fig.~\ref{fig:splicecp_data_flux}.
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[height=6cm]{img/splice_copy}
+  \includegraphics[height=4cm]{img/splice_copy}
   \caption{Struttura del flusso di dati usato dal programma \texttt{splicecp}.}
   \label{fig:splicecp_data_flux}
 \end{figure}
 
-Una volta trattate le opzioni il programma verifica che restino
-(\texttt{\small 13-16}) i due argomenti che indicano il file sorgente ed il
-file destinazione. Il passo successivo è aprire il file sorgente
-(\texttt{\small 18-22}), quello di destinazione (\texttt{\small 23-27}) ed
-infine (\texttt{\small 28-31}) la \textit{pipe} che verrà usata come buffer.
+Il programma si chiama \texttt{splicecp.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, le funzioni di ausilio, le
+aperture dei file di ingresso e di uscita passati come argomenti e quella
+della \textit{pipe} intermedia, è riportato in fig.~\ref{fig:splice_example}.
 
-\begin{figure}[!htbp]
+\begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{\codesamplewidth}
     \includecodesample{listati/splicecp.c}
@@ -5159,29 +5237,30 @@ infine (\texttt{\small 28-31}) la \textit{pipe} che verrà usata come buffer.
   \label{fig:splice_example}
 \end{figure}
 
-Il ciclo principale (\texttt{\small 33-58}) inizia con la lettura dal file
-sorgente tramite la prima \func{splice} (\texttt{\small 34-35}), in questo
+Il ciclo principale (\texttt{\small 13-38}) inizia con la lettura dal file
+sorgente tramite la prima \func{splice} (\texttt{\small 14-15}), in questo
 caso si è usato come primo argomento il file descriptor del file sorgente e
-come terzo quello del capo in scrittura della \textit{pipe} (il funzionamento
+come terzo quello del capo in scrittura della \textit{pipe}. Il funzionamento
 delle \textit{pipe} e l'uso della coppia di file descriptor ad esse associati
 è trattato in dettaglio in sez.~\ref{sec:ipc_unix}; non ne parleremo qui dato
 che nell'ottica dell'uso di \func{splice} questa operazione corrisponde
-semplicemente al trasferimento dei dati dal file al buffer).
+semplicemente al trasferimento dei dati dal file al buffer in \textit{kernel
+  space}.
 
 La lettura viene eseguita in blocchi pari alla dimensione specificata
 dall'opzione \texttt{-s} (il default è 4096); essendo in questo caso
 \func{splice} equivalente ad una \func{read} sul file, se ne controlla il
 valore di uscita in \var{nread} che indica quanti byte sono stati letti, se
-detto valore è nullo (\texttt{\small 36}) questo significa che si è giunti
+detto valore è nullo (\texttt{\small 16}) questo significa che si è giunti
 alla fine del file sorgente e pertanto l'operazione di copia è conclusa e si
 può uscire dal ciclo arrivando alla conclusione del programma (\texttt{\small
-  59}). In caso di valore negativo (\texttt{\small 37-44}) c'è stato un
-errore ed allora si ripete la lettura (\texttt{\small 36}) se questo è dovuto
+  59}). In caso di valore negativo (\texttt{\small 17-24}) c'è stato un
+errore ed allora si ripete la lettura (\texttt{\small 16}) se questo è dovuto
 ad una interruzione, o altrimenti si esce con un messaggio di errore
-(\texttt{\small 41-43}).
+(\texttt{\small 21-23}).
 
 Una volta completata con successo la lettura si avvia il ciclo di scrittura
-(\texttt{\small 45-57}); questo inizia (\texttt{\small 46-47}) con la
+(\texttt{\small 25-37}); questo inizia (\texttt{\small 26-27}) con la
 seconda \func{splice} che cerca di scrivere gli \var{nread} byte letti, si
 noti come in questo caso il primo argomento faccia di nuovo riferimento alla
 \textit{pipe} (in questo caso si usa il capo in lettura, per i dettagli si
@@ -5191,8 +5270,8 @@ del file di destinazione.
 Di nuovo si controlla il numero di byte effettivamente scritti restituito in
 \var{nwrite} e in caso di errore al solito si ripete la scrittura se questo è
 dovuto a una interruzione o si esce con un messaggio negli altri casi
-(\texttt{\small 48-55}). Infine si chiude il ciclo di scrittura sottraendo
-(\texttt{\small 57}) il numero di byte scritti a quelli di cui è richiesta la
+(\texttt{\small 28-35}). Infine si chiude il ciclo di scrittura sottraendo
+(\texttt{\small 37}) il numero di byte scritti a quelli di cui è richiesta la
 scrittura,\footnote{in questa parte del ciclo \var{nread}, il cui valore
   iniziale è dato dai byte letti dalla precedente chiamata a \func{splice},
   viene ad assumere il significato di byte da scrivere.} così che il ciclo di
@@ -5681,6 +5760,9 @@ livello di kernel.
 % nel kernel 3.15 (sul secondo vedi http://lwn.net/Articles/589260/), vedi
 % anche http://lwn.net/Articles/629965/
 
+% TODO aggiungere FALLOC_FL_INSERT vedi  http://lwn.net/Articles/629965/
+
+
 % TODO non so dove trattarli, ma dal 2.6.39 ci sono i file handle, vedi
 % http://lwn.net/Articles/432757/ 
 
@@ -5740,11 +5822,12 @@ livello di kernel.
 % LocalWords:  sigwaitinfo FifoReporter Windows ptr sigqueue named timerfd TFD
 % LocalWords:  clockid CLOCK MONOTONIC REALTIME itimerspec interval Resource
 % LocalWords:  ABSTIME gettime temporarily unavailable SIGINT SIGQUIT SIGTERM
+% LocalWords:  sigfd fifofd break siginf names starting echo Message from Got
+% LocalWords:  message kill received means exit TLOCK ULOCK EPOLLWAKEUP
 
 
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "gapil"
 %%% End: 
-% LocalWords:  sigfd fifofd break siginf names starting echo Message from Got
-% LocalWords:  message kill received means exit
+