X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=blobdiff_plain;f=fileadv.tex;h=e5313642070f22b19db1e8308888fe2eaf70ae52;hb=936ae71ad2a06b154b23470ef38f477af32e67fe;hp=0ef7c30f026a5e6d85fe7582674f75f5dd0a5b2f;hpb=7a51b7bb2f39f6a4c5ad3f1dfcf6eda60d7eec38;p=gapil.git diff --git a/fileadv.tex b/fileadv.tex index 0ef7c30..e531364 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -3907,12 +3907,12 @@ Il meccanismo è illustrato in fig.~\ref{fig:file_mmap_layout}, una sezione del file viene \textsl{mappata} direttamente nello spazio degli indirizzi del programma. Tutte le operazioni di lettura e scrittura su variabili contenute in questa zona di memoria verranno eseguite leggendo e scrivendo dal contenuto -del file attraverso il sistema della memoria virtuale \index{memoria~virtuale} -che in maniera analoga a quanto avviene per le pagine che vengono salvate e -rilette nella swap, si incaricherà di sincronizzare il contenuto di quel -segmento di memoria con quello del file mappato su di esso. Per questo motivo -si può parlare tanto di \textsl{file mappato in memoria}, quanto di -\textsl{memoria mappata su file}. +del file attraverso il sistema della memoria virtuale illustrato in +sez.~\ref{sec:proc_mem_gen} che in maniera analoga a quanto avviene per le +pagine che vengono salvate e rilette nella \textit{swap}, si incaricherà di +sincronizzare il contenuto di quel segmento di memoria con quello del file +mappato su di esso. Per questo motivo si può parlare tanto di \textsl{file + mappato in memoria}, quanto di \textsl{memoria mappata su file}. L'uso del \textit{memory-mapping} comporta una notevole semplificazione delle operazioni di I/O, in quanto non sarà più necessario utilizzare dei buffer @@ -3928,12 +3928,12 @@ 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 swap. +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 -scritte sulla swap; questo consente di accedere ai file su dimensioni il cui -solo limite è quello dello spazio di indirizzi disponibile, e non della +scritte sulla \textit{swap}; questo consente di accedere ai file su dimensioni +il cui solo limite è quello dello spazio di indirizzi disponibile, e non della memoria su cui possono esserne lette delle porzioni. L'interfaccia POSIX implementata da Linux prevede varie funzioni di sistema @@ -3941,7 +3941,6 @@ per la gestione del \textit{memory mapped I/O}, la prima di queste, che serve ad eseguire la mappatura in memoria di un file, è \funcd{mmap}; il suo prototipo è: - \begin{funcproto}{ \fhead{unistd.h} \fhead{sys/mman.h} @@ -3951,8 +3950,8 @@ prototipo è: } {La funzione ritorna il puntatore alla zona di memoria mappata in caso di - successo, e \const{MAP\_FAILED} ($-1$) per un errore, nel qual caso - \var{errno} assumerà uno dei valori: + successo, e \const{MAP\_FAILED} (\texttt{(void *) -1}) per un errore, nel + qual caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EACCES}] o \param{fd} non si riferisce ad un file regolare, o si è usato \const{MAP\_PRIVATE} ma \param{fd} non è aperto in lettura, @@ -3966,13 +3965,19 @@ prototipo è: \const{MAP\_ANONYMOUS}. \item[\errcode{EINVAL}] i valori di \param{start}, \param{length} o \param{offset} non sono validi (o troppo grandi o non allineati sulla - dimensione delle pagine). + dimensione delle pagine), o \param{lengh} è zero (solo dal 2.6.12) + o \param{flags} contiene sia \const{MAP\_PRIVATE} che + \const{MAP\_SHARED} o nessuno dei due. \item[\errcode{ENFILE}] si è superato il limite del sistema sul numero di file aperti (vedi sez.~\ref{sec:sys_resource_limit}). \item[\errcode{ENODEV}] il filesystem di \param{fd} non supporta il memory mapping. \item[\errcode{ENOMEM}] non c'è memoria o si è superato il limite sul numero di mappature possibili. + \item[\errcode{EOVERFLOW}] su architettura a 32 bit con il supporto per i + \textit{large file} (che hanno una dimensione a 64 bit) il numero di + pagine usato per \param{lenght} aggiunto a quello usato + per \param{offset} eccede i 32 bit (\texttt{unsigned long}). \item[\errcode{EPERM}] l'argomento \param{prot} ha richiesto \const{PROT\_EXEC}, ma il filesystem di \param{fd} è montato con l'opzione \texttt{noexec}. @@ -3982,14 +3987,14 @@ prototipo è: } \end{funcproto} - La funzione richiede di mappare in memoria la sezione del file \param{fd} a partire da \param{offset} per \param{length} byte, preferibilmente all'indirizzo \param{start}. Il valore \param{start} viene normalmente -considerato come un suggerimento, ma l'uso di un valore diverso da \val{NULL}, -in cui di rimette completamente al kernel la scelta dell'indirizzo, viene -sconsigliato per ragioni di portabilità. Il valore di \param{offset} deve -essere un multiplo della dimensione di una pagina di memoria. +considerato come un suggerimento, ma l'uso di un qualunque valore diverso da +\val{NULL}, in cui si rimette completamente al kernel la scelta +dell'indirizzo, viene sconsigliato per ragioni di portabilità. Il valore +di \param{offset} deve essere un multiplo della dimensione di una pagina di +memoria. \begin{table}[htb] \centering @@ -4012,8 +4017,8 @@ essere un multiplo della dimensione di una pagina di memoria. Il valore dell'argomento \param{prot} indica la protezione\footnote{come accennato in sez.~\ref{sec:proc_memory} in Linux la memoria reale è divisa - in pagine: ogni processo vede la sua memoria attraverso uno o più segmenti - lineari di memoria virtuale. Per ciascuno di questi segmenti il kernel + in pagine, ogni processo vede la sua memoria attraverso uno o più segmenti + lineari di memoria virtuale; per ciascuno di questi segmenti il kernel mantiene nella \itindex{page~table} \textit{page table} la mappatura sulle pagine di memoria reale, ed le modalità di accesso (lettura, esecuzione, scrittura); una loro violazione causa quella una \itindex{segment~violation} @@ -4062,26 +4067,25 @@ tab.~\ref{tab:file_mmap_flag}. \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} \textit{stack}. Indica che la mappatura deve essere effettuata con gli indirizzi crescenti verso il basso.\\ - \const{MAP\_HUGETLB} & da trattare (dal 2.6.32).\\ - \const{MAP\_LOCKED} & Se impostato impedisce lo swapping delle pagine - mappate (dal 2.5.37).\\ + \const{MAP\_HUGETLB} & Esegue la mappatura usando le cosiddette + ``\textit{huge pages}'' (dal 2.6.32).\\ + \const{MAP\_LOCKED} & Se impostato impedisce lo \textit{swapping} delle + pagine mappate (dal 2.5.37).\\ \const{MAP\_NONBLOCK} & Esegue un \textit{prefaulting} più limitato che non causa I/O (dal 2.5.46).\\ \const{MAP\_NORESERVE} & Si usa con \const{MAP\_PRIVATE}. Non riserva - delle pagine di swap ad uso del meccanismo del - \textit{copy on write} \itindex{copy~on~write} - per mantenere le - modifiche fatte alla regione mappata, in - questo caso dopo una scrittura, se non c'è più - memoria disponibile, si ha l'emissione di - un \signal{SIGSEGV}.\\ + delle pagine di \textit{swap} ad uso del meccanismo + del \textit{copy on write} \itindex{copy~on~write} + per mantenere le modifiche fatte alla regione + mappata, in questo caso dopo una scrittura, se + non c'è più memoria disponibile, si ha + l'emissione di un \signal{SIGSEGV}.\\ \const{MAP\_PRIVATE} & I cambiamenti sulla memoria mappata non vengono riportati sul file. Ne viene fatta una copia privata cui solo il processo chiamante ha accesso. Le modifiche sono mantenute attraverso - il meccanismo del \textit{copy on - write} \itindex{copy~on~write} e - salvate su swap in caso di necessità. Non è + il meccanismo del \textit{copy on write} e + salvate su \textit{swap} in caso di necessità. Non è specificato se i cambiamenti sul file originale vengano riportati sulla regione mappata. Incompatibile con \const{MAP\_SHARED}.\\ @@ -4144,25 +4148,22 @@ effettive del file o della sezione che si vuole mappare. Il caso più comune è quello illustrato in fig.~\ref{fig:file_mmap_boundary}, in cui la sezione di file non rientra nei confini di una pagina: in tal caso verrà il file sarà mappato su un segmento di memoria che si estende fino al -bordo della pagina successiva. - -In questo caso è possibile accedere a quella zona di memoria che eccede le -dimensioni specificate da \param{length}, senza ottenere un \signal{SIGSEGV} -poiché essa è presente nello spazio di indirizzi del processo, anche se non è -mappata sul file. Il comportamento del sistema è quello di restituire un -valore nullo per quanto viene letto, e di non riportare su file quanto viene -scritto. +bordo della pagina successiva. In questo caso è possibile accedere a quella +zona di memoria che eccede le dimensioni specificate da \param{length}, senza +ottenere un \signal{SIGSEGV} poiché essa è presente nello spazio di indirizzi +del processo, anche se non è mappata sul file. Il comportamento del sistema è +quello di restituire un valore nullo per quanto viene letto, e di non +riportare su file quanto viene scritto. Un caso più complesso è quello che si viene a creare quando le dimensioni del file mappato sono più corte delle dimensioni della mappatura, oppure quando il file è stato troncato, dopo che è stato mappato, ad una dimensione inferiore a -quella della mappatura in memoria. - -In questa situazione, per la sezione di pagina parzialmente coperta dal -contenuto del file, vale esattamente quanto visto in precedenza; invece per la -parte che eccede, fino alle dimensioni date da \param{length}, l'accesso non -sarà più possibile, ma il segnale emesso non sarà \signal{SIGSEGV}, ma -\signal{SIGBUS}, come illustrato in fig.~\ref{fig:file_mmap_exceed}. +quella della mappatura in memoria. In questa situazione, per la sezione di +pagina parzialmente coperta dal contenuto del file, vale esattamente quanto +visto in precedenza; invece per la parte che eccede, fino alle dimensioni date +da \param{length}, l'accesso non sarà più possibile, ma il segnale emesso non +sarà \signal{SIGSEGV}, ma \signal{SIGBUS}, come illustrato in +fig.~\ref{fig:file_mmap_exceed}. Non tutti i file possono venire mappati in memoria, dato che, come illustrato in fig.~\ref{fig:file_mmap_layout}, la mappatura introduce una corrispondenza @@ -4477,38 +4478,39 @@ partire dal quale la sezione di file indicata verrà rimappata. L'argomento valori di \func{mmap} (quelli di tab.~\ref{tab:file_mmap_prot}) ma di tutti i flag solo \const{MAP\_NONBLOCK} non viene ignorato. +\itindbeg{prefaulting} + Insieme alla funzione \func{remap\_file\_pages} nel kernel 2.5.46 con sono stati introdotti anche due nuovi flag per \func{mmap}: \const{MAP\_POPULATE} e \const{MAP\_NONBLOCK}. Il primo dei due consente di abilitare il meccanismo -del \itindex{prefaulting} \textit{prefaulting}. Questo viene di nuovo in aiuto -per migliorare le prestazioni in certe condizioni di utilizzo del -\textit{memory mapping}. +del \textit{prefaulting}. Questo viene di nuovo in aiuto per migliorare le +prestazioni in certe condizioni di utilizzo del \textit{memory mapping}. Il problema si pone tutte le volte che si vuole mappare in memoria un file di -grosse dimensioni. Il comportamento normale del sistema della -\index{memoria~virtuale} memoria virtuale è quello per cui la regione mappata -viene aggiunta alla \itindex{page~table} \textit{page table} del processo, ma -i dati verranno effettivamente utilizzati (si avrà cioè un -\itindex{page~fault} \textit{page fault} che li trasferisce dal disco alla -memoria) soltanto in corrispondenza dell'accesso a ciascuna delle pagine -interessate dal \textit{memory mapping}. +grosse dimensioni. Il comportamento normale del sistema della memoria virtuale +è quello per cui la regione mappata viene aggiunta alla \textit{page table} +del processo, ma i dati verranno effettivamente utilizzati (si avrà cioè un +\textit{page fault} che li trasferisce dal disco alla memoria) soltanto in +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 \itindex{prefaulting} -\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}. +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 -flag, \const{MAP\_NONBLOCK}, che esegue un \itindex{prefaulting} -\textit{prefaulting} più limitato in cui vengono popolate solo le pagine della -mappatura che già si trovano nella cache del kernel.\footnote{questo può - essere utile per il linker dinamico, in particolare quando viene effettuato - il \textit{prelink} delle applicazioni.} +flag, \const{MAP\_NONBLOCK}, che esegue un \textit{prefaulting} più limitato +in cui vengono popolate solo le pagine della mappatura che già si trovano +nella cache del kernel.\footnote{questo può essere utile per il linker + dinamico, in particolare quando viene effettuato il \textit{prelink} delle + applicazioni.} + +\itindend{prefaulting} Per i vantaggi illustrati all'inizio del paragrafo l'interfaccia del \textit{memory mapped I/O} viene usata da una grande varietà di programmi, @@ -5381,11 +5383,10 @@ all'accesso al disco; il suo prototipo è: La funzione richiede che venga letto in anticipo il contenuto del file \param{fd} a partire dalla posizione \param{offset} e per un ammontare di -\param{count} byte, in modo da portarlo in cache. La funzione usa la -\index{memoria~virtuale} memoria virtuale ed il meccanismo della -\index{paginazione} paginazione per cui la lettura viene eseguita in blocchi -corrispondenti alle dimensioni delle pagine di memoria, ed i valori di -\param{offset} e \param{count} vengono arrotondati di conseguenza. +\param{count} byte, in modo da portarlo in cache. La funzione usa la memoria +virtuale ed il meccanismo della paginazione per cui la lettura viene eseguita +in blocchi corrispondenti alle dimensioni delle pagine di memoria, ed i valori +di \param{offset} e \param{count} vengono arrotondati di conseguenza. La funzione estende quello che è un comportamento normale del kernel che quando si legge un file, aspettandosi che l'accesso prosegua, esegue sempre