X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=fileadv.tex;h=4761523154cd2904385bb04b0817431e1f6ab982;hp=14e10b8af985199c54470814e0862c08685d43b9;hb=154622c3382b558d8c0b7984ee76d96d09d44c71;hpb=250b32a55733b307d2eae8afb50b64af1b7c0bc8 diff --git a/fileadv.tex b/fileadv.tex index 14e10b8..4761523 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -3010,7 +3010,7 @@ definito la macro \macro{\_GNU\_SOURCE},\footnote{si ricordi che questa } \end{functions} -La funzione esegue un trasferimento di \param{count} byte dal file descriptor +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 @@ -3041,32 +3041,154 @@ Ovviamente soltanto uno di questi due argomenti, e pi 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}. - +Infine l'argomento \param{flags} 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}. Alcuni di questi valori vengono utilizzati anche +dalle funzioni \func{vmslice} e \func{tee} per cui la tabella riporta le +descrizioni complete di tutti i valori possibili anche quando, come per +\const{SPLICE\_F\_GIFT}, questi non hanno effetto su \func{splice}. \begin{table}[htb] \centering \footnotesize - \begin{tabular}[c]{|l|p{8cm}|} + \begin{tabular}[c]{|l|p{10cm}|} \hline \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{SPLICE\_F\_MOVE} & .\\ - \const{SPLICE\_F\_NONBLOCK}& .\\ - \const{SPLICE\_F\_MORE} & .\\ - \const{SPLICE\_F\_GIFT} & .\\ + \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}.\\ + \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 + \textit{pipe}. Nel caso di \func{splice} + questo significa che la funzione potrà + comunque bloccarsi nell'accesso agli altri + file descriptor (a meno che anch'essi non + siano stati aperti in modalità non + bloccante).\\ + \const{SPLICE\_F\_MORE} & Indica al kernel che ci sarà l'invio di + 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 + implementato in futuro anche per + \func{vmslice} 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 + usa \const{SPLICE\_F\_MOVE} potrà spostare le + pagine con successo, altrimenti esse dovranno + essere copiate; per usare questa opzione i + dati dovranno essere opportunamente allineati + in posizione ed in dimensione alle pagine di + memoria. Viene usato soltanto da + \func{vmsplice}.\\ \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}.} + dell'argomento \param{flags} di \func{slice}, \func{vmslice} e \func{tee}.} \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 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{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}. + +\begin{figure}[htb] + \centering + \includegraphics[height=6cm]{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. + + +\begin{figure}[!htbp] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/splicecp.c} + \end{minipage} + \normalsize + \caption{Esempio di codice che usa \func{splice} per effettuare la copia di + un file.} + \label{fig:splice_example} +\end{figure} +Il ciclo principale (\texttt{\small 33--59}) inizia con la lettura dal file +sorgente tramite la prima \func{splice} (\texttt{\small 34--35}), 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 +delle \textit{pipe} è trattato in dettaglio in sez.~\ref{sec:ipc_unix}, +nell'ottica dell'uso di \func{splice} questa operazione corrisponde +semplicemente alla copia dei dati dal file al buffer). + +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 +nullo (\texttt{\small 36}) questo significa che si è giunti alla fine del file +sorgente e pertanto l'operazione di copia è conclusa e si può uscire dal +ciclo. In caso di valore negativo c'è stato un errore ed allora si ripete la +lettura se questo è dovuto ad una interruzione, o si esce altrimenti +(\texttt{\small 37--44}). + +Una volta completata con successo la lettura si avvia il ciclo di scrittura +(\texttt{\small 45--58}); questo inizia (\texttt{\small 46--47}) con la +seconda \func{splice} che cerca di scrivere gli \var{nread} byte letti, si +noti come in questo caso il primo argomento sia il capo in lettura della +\textit{pipe} ed il terzo il file descriptor del file di destinazione. + +Di nuovo si controlla il numero di byte effettivamente scritti restituito in +\var{nwrite} e se nullo (\texttt{\small 48}) si ripete la scrittura (in realtà +questo non avverrà mai), in caso di errore (\texttt{\small 49--56}) al solito +si ripete la scrittura se questo è dovuto a una interruzione o si esce con un +messaggio negli altri casi. + +Infine si chiude il ciclo di scrittura sottraendo (\texttt{\small 57}) il +numero di byte scritti a quelli letti, così che il ciclo di scrittura venga +ripetuto (\texttt{\small 58}) qualora la chiamata a \func{splice} non abbia +esaurito tutti i dati presenti sul buffer. + +Si noti come il programma sia concettualmente identico a quello che si sarebbe +scritto usando \func{read} al posto della prima \func{splice} e \func{write} al +posto della seconda, utilizzando un buffer in user space per eseguire la copia +dei file, solo che in questo caso non è stato necessario allocare nessun +buffer e non si è trasferito nessun dato in user space. % TODO documentare le funzioni tee e splice