operazioni in DMA su quelle pagine.\\
\const{MADV\_DOFORK} & rimuove l'effetto della precedente
\const{MADV\_DONTFORK}.\\
+ \const{MADV\_MERGEABLE}& marca la pagina come accorpabile (indicazione
+ principalmente ad uso dei sistemi di
+ virtualizzazione).\footnotemark\\
\hline
\end{tabular}
\caption{Valori dell'argomento \param{advice} di \func{madvise}.}
\label{tab:madvise_advice_values}
\end{table}
-%TODO aggiungere MADV_MERGEABLE, vedi http://kernelnewbies.org/Linux_2_6_32
-
\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
+ di controllare tutte le pagine solo quelle marcate con questo flag vengono
+ prese in considerazione per l'accorpamento; in questo modo si possono
+ migliorare le prestazioni nella gestione delle macchine virtuali diminuendo
+ 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}}.}
+
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
Si tenga presente infine che queste funzioni operano sui file con
l'interfaccia dei file descriptor, e non è consigliabile mescolarle con
-l'interfaccia classica dei \textit{file stream}; a causa delle bufferizzazioni
-interne di quest'ultima infatti si potrebbero avere risultati indefiniti e non
-corrispondenti a quanto aspettato.
+l'interfaccia classica dei \textit{file stream} di
+cap.~\ref{cha:files_std_interface}; a causa delle bufferizzazioni interne di
+quest'ultima infatti si potrebbero avere risultati indefiniti e non
+corrispondenti a quanto aspettato.
Come per le normali operazioni di lettura e scrittura, anche per l'\textsl{I/O
vettorizzato} si pone il problema di poter effettuare le operazioni in
-maniera atomica a partire da un certa posizione sul file; per questo motivo a
+maniera atomica a partire da un certa posizione sul file. Per questo motivo a
partire dal kernel 2.6.30 sono state introdotte anche per l'\textsl{I/O
vettorizzato} le analoghe delle funzioni \func{pread} e \func{pwrite} (vedi
-sez.~\ref{sec:file_read} e \ref{sec:file_write}) che consentono di effettuare
-letture e scritture vettorizzate a partire da una certa posizione. Le due
-funzioni sono \funcd{preadv} e \func{pwritev} ed i rispettivi prototipi sono:
+sez.~\ref{sec:file_read} e \ref{sec:file_write}); le due funzioni sono
+\funcd{preadv} e \func{pwritev} ed i rispettivi prototipi sono:\footnote{le
+ due funzioni sono analoghe alle omonime presenti in BSD; le \textit{system
+ call} usate da Linux (introdotte a partire dalla versione 2.6.30)
+ utilizzano degli argomenti diversi per problemi collegati al formato a 64
+ 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
+ offset)}
+ \funcdecl{int pwritev(int fd, const struct iovec *vector, int count, off\_t
+ offset)}
+
+ 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 \ctyp{off\_t}.
+ \item[\errcode{ESPIPE}] \param{fd} è associato ad un socket o una pipe.
+ \end{errlist}
+}
+\end{functions}
-% TODO verificare cosa succederà a preadv e pwritev o alla nuova niovec
-% vedi http://lwn.net/Articles/164887/
-% inserite nel kernel 2.6.30, vedi http://lwn.net/Articles/326818/
+Le due funzioni eseguono rispettivamente una lettura o una scrittura
+vettorizzata a partire dalla posizione \param{offset} sul file indicato
+da \param{fd}, la posizione corrente sul file, come vista da eventuali altri
+processi che vi facciano riferimento, non viene alterata. A parte la presenza
+dell'ulteriore argomento il comportamento delle funzioni è identico alle
+precedenti \func{readv} e \func{writev}.
+
+Con l'uso di queste funzioni si possono evitare eventuali
+\itindex{race~condition} \textit{race conditions} quando si deve eseguire la
+una operazione di lettura e scrittura vettorizzata a partire da una certa
+posizione su un file, mentre al contempo si possono avere in concorrenza
+processi che utilizzano lo stesso file descriptor (si ricordi quanto visto in
+sez.~\ref{sec:file_adv_func}) con delle chiamate a \func{lseek}.
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};\footnote{la funzione è stata
+La prima funzione che è stata ideata per ottimizzare il trasferimento dei dati
+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 suo
-prototipo è:
+utilizzati prototipi e semantiche differenti; nel caso di Linux il prototipo
+di \funcd{sendfile} è:
\begin{functions}
\headdecl{sys/sendfile.h}
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
+\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}.
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
+prestazioni, resta il dubbio se la scelta di disabilitarla sempre per il
+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
\label{tab:splice_flag}
\end{table}
-\footnotetext{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 pipe o il buffer non corrisponda a pagine intere esse saranno
- comunque copiate.}
+\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 pipe o il buffer non corrisponda a pagine intere esse
+ saranno comunque copiate.}
-\footnotetext{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[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
La prima funzione, \funcd{vmsplice}, è la più simile a \func{splice} e come
indica il suo nome consente di trasferire i dati dalla memoria di un processo
-verso una \textit{pipe}, il suo prototipo è:
+(ad esempio per un file mappato in memoria) verso una \textit{pipe}, il suo
+prototipo è:
\begin{functions}
\headdecl{fcntl.h}
\headdecl{sys/uio.h}
}
\end{functions}
-La \textit{pipe} dovrà essere specificata tramite il file descriptor
-corrispondente al suo capo aperto in scrittura (di nuovo si faccia riferimento
-a sez.~\ref{sec:ipc_unix}), mentre per indicare quali zone di memoria devono
-essere trasferita si deve utilizzare un vettore di strutture \struct{iovec}
-(vedi fig.~\ref{fig:file_iovec}), con le stesse con cui le si usano per l'I/O
-vettorizzato; le dimensioni del suddetto vettore devono essere passate
+La \textit{pipe} indicata da \param{fd} dovrà essere specificata tramite il
+file descriptor corrispondente al suo capo aperto in scrittura (di nuovo si
+faccia riferimento a sez.~\ref{sec:ipc_unix}), mentre per indicare quali zone
+di memoria devono essere trasferita si dovrà utilizzare un vettore di
+strutture \struct{iovec} (vedi fig.~\ref{fig:file_iovec}), esattamente con gli
+stessi criteri con cui le si usano per l'I/O vettorizzato, indicando gli
+indirizzi e le dimensioni di ciascun segmento di memoria su cui si vuole
+operare; le dimensioni del suddetto vettore devono essere passate
nell'argomento \param{nr\_segs} che indica il numero di segmenti di memoria da
trasferire. Sia per il vettore che per il valore massimo di \param{nr\_segs}
valgono le stesse limitazioni illustrate in sez.~\ref{sec:file_multiple_io}.
In caso di successo la funzione ritorna il numero di byte trasferiti sulla
-pipe, in generale (se i dati una volta creati non devono essere riutilizzati)
-è opportuno utilizzare il flag \const{SPLICE\_F\_GIFT}; questo fa si che il
-kernel possa rimuovere le relative pagine dallo spazio degli indirizzi del
-processo, e scaricarle nella cache, così che queste possono essere utilizzate
+\textit{pipe}. In generale, se i dati una volta creati non devono essere
+riutilizzati (se cioè l'applicazione che chiama \func{vmsplice} non
+modificherà più la memoria trasferita), è opportuno utilizzare
+per \param{flag} il valore \const{SPLICE\_F\_GIFT}; questo fa sì che il kernel
+possa rimuovere le relative pagine dallo spazio degli indirizzi del processo,
+e scaricarle nella cache, così che queste possono essere utilizzate
immediatamente senza necessità di eseguire una copia dei dati che contengono.
La seconda funzione aggiunta insieme a \func{splice} è \func{tee}, che deve il