Altre correzioni di indicizzazioni. Introdotta mremap. Aggiornati i flag di
[gapil.git] / fileadv.tex
index 25e62d309ed63c23836e822dfab643c1c1901845..6a94f22492fa08ef6ca8047c9e49681ca23d269d 100644 (file)
@@ -998,7 +998,7 @@ si pu
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=14cm]{img/mmap_layout}
+  \includegraphics[width=13cm]{img/mmap_layout}
   \caption{Disposizione della memoria di un processo quando si esegue la
   mappatura in memoria di un file.}
   \label{fig:file_mmap_layout}
@@ -1094,11 +1094,11 @@ multiplo della dimensione di una pagina di memoria.
 Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux
   la memoria reale è divisa in pagine: ogni processo vede la sua memoria
   attraverso uno o più segmenti lineari di memoria virtuale.  Per ciascuno di
-  questi segmenti il kernel mantiene nella \textit{page table} la mappatura
-  sulle pagine di memoria reale, ed le modalità di accesso (lettura,
-  esecuzione, scrittura); una loro violazione causa quella che si chiama una
-  \textit{segment violation}, e la relativa emissione del segnale
-  \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere
+  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
+  che si chiama una \textit{segment violation}, e la relativa emissione del
+  segnale \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere
 specificato come maschera binaria ottenuta dall'OR di uno o più dei valori
 riportati in tab.~\ref{tab:file_mmap_flag}; il valore specificato deve essere
 compatibile con la modalità di accesso con cui si è aperto il file.
@@ -1155,7 +1155,7 @@ tab.~\ref{tab:file_mmap_flag}.
                              memoria disponibile, si ha l'emissione di
                              un \const{SIGSEGV}. \\
     \const{MAP\_LOCKED}    & Se impostato impedisce lo swapping delle pagine
-                             mappate. \\
+                             mappate.\\
     \const{MAP\_GROWSDOWN} & Usato per gli stack. Indica 
                              che la mappatura deve essere effettuata con gli
                              indirizzi crescenti verso il basso.\\
@@ -1163,17 +1163,26 @@ tab.~\ref{tab:file_mmap_flag}.
                              argomenti \param{fd} e \param{offset} sono
                              ignorati.\footnotemark\\
     \const{MAP\_ANON}      & Sinonimo di \const{MAP\_ANONYMOUS}, deprecato.\\
-    \const{MAP\_FILE}      & Valore di compatibilità, deprecato.\\
+    \const{MAP\_FILE}      & Valore di compatibilità, ignorato.\\
+    \const{MAP\_32BIT}     & Esegue la mappatura sui primi 2GiB dello spazio
+                             degli indirizzi, viene supportato solo sulle
+                             piattaforme \texttt{x86-64} per compatibilità con
+                             le applicazioni a 32 bit. Viene ignorato se si è
+                             richiesto \const{MAP\_FIXED}.\\
+    \const{MAP\_POPULATE}  & Esegue il \itindex{prefaulting}
+                             \textit{prefaulting} delle pagine di memoria
+                             necessarie alla mappatura. \\
+    \const{MAP\_NONBLOCK}  & Esegue un \textit{prefaulting} più limitato che
+                             non causa I/O.\footnotemark \\
+%     \const{MAP\_DONTEXPAND}& Non consente una successiva espansione dell'area
+%                              mappata con \func{mremap}, proposto ma pare non
+%                              implementato.\\
     \hline
   \end{tabular}
   \caption{Valori possibili dell'argomento \param{flag} di \func{mmap}.}
   \label{tab:file_mmap_flag}
 \end{table}
 
-\footnotetext{Dato che tutti faranno riferimento alle stesse pagine di
-  memoria.}  
-\footnotetext{L'uso di questo flag con \const{MAP\_SHARED} è
-  stato implementato in Linux a partire dai kernel della serie 2.4.x.}
 
 Gli effetti dell'accesso ad una zona di memoria mappata su file possono essere
 piuttosto complessi, essi si possono comprendere solo tenendo presente che
@@ -1184,14 +1193,6 @@ sola lettura si avr
 (\const{SIGSEGV}), dato che i permessi sul segmento di memoria relativo non
 consentono questo tipo di accesso.
 
-\begin{figure}[!htb]
-  \centering
-  \includegraphics[width=10cm]{img/mmap_boundary}
-  \caption{Schema della mappatura in memoria di una sezione di file di
-    dimensioni non corrispondenti al bordo di una pagina.}
-  \label{fig:file_mmap_boundary}
-\end{figure}
-
 È invece assai diversa la questione relativa agli accessi al di fuori della
 regione di cui si è richiesta la mappatura. A prima vista infatti si potrebbe
 ritenere che anch'essi debbano generare un segnale di violazione di accesso;
@@ -1199,11 +1200,30 @@ questo per
 paginazione\index{paginazione}, la mappatura in memoria non può che essere
 eseguita su un segmento di dimensioni rigorosamente multiple di quelle di una
 pagina, ed in generale queste potranno non corrispondere alle dimensioni
-effettive del file o della sezione che si vuole mappare. 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.
+effettive del file o della sezione che si vuole mappare. 
+
+\footnotetext[20]{Dato che tutti faranno riferimento alle stesse pagine di
+  memoria.}  
+\footnotetext[21]{L'uso di questo flag con \const{MAP\_SHARED} è
+  stato implementato in Linux a partire dai kernel della serie 2.4.x.}
+
+\footnotetext{questo flag ed il precedente \const{MAP\_POPULATE} sono stati
+  introdotti nel kernel 2.5.46 insieme alla mappatura non lineare di cui
+  parleremo più avanti.}
+
+\begin{figure}[!htb] 
+  \centering
+  \includegraphics[width=10cm]{img/mmap_boundary}
+  \caption{Schema della mappatura in memoria di una sezione di file di
+    dimensioni non corrispondenti al bordo di una pagina.}
+  \label{fig:file_mmap_boundary}
+\end{figure}
+
+
+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{lenght}, senza ottenere un \const{SIGSEGV}
@@ -1217,14 +1237,6 @@ file mappato sono pi
 file è stato troncato, dopo che è stato mappato, ad una dimensione inferiore a
 quella della mappatura in memoria.
 
-\begin{figure}[htb]
-  \centering
-  \includegraphics[width=10cm]{img/mmap_exceed}
-  \caption{Schema della mappatura in memoria di file di dimensioni inferiori
-    alla lunghezza richiesta.}
-  \label{fig:file_mmap_exceed}
-\end{figure}
-
 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
@@ -1242,6 +1254,14 @@ sez.~\ref{sec:file_vfs_work}). Si tenga presente per
 di dispositivi (un esempio è l'interfaccia al ponte PCI-VME del chip Universe)
 che sono utilizzabili solo con questa interfaccia.
 
+\begin{figure}[htb]
+  \centering
+  \includegraphics[width=10cm]{img/mmap_exceed}
+  \caption{Schema della mappatura in memoria di file di dimensioni inferiori
+    alla lunghezza richiesta.}
+  \label{fig:file_mmap_exceed}
+\end{figure}
+
 Dato che passando attraverso una \func{fork} lo spazio di indirizzi viene
 copiato integralmente, i file mappati in memoria verranno ereditati in maniera
 trasparente dal processo figlio, mantenendo gli stessi attributi avuti nel
@@ -1293,8 +1313,9 @@ memoria mappata con il file su disco; il suo prototipo 
   \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
     errore nel qual caso \var{errno} assumerà uno dei valori:
     \begin{errlist}
-    \item[\errcode{EINVAL}] O \param{start} non è multiplo di \const{PAGESIZE},
-    o si è specificato un valore non valido per \param{flags}.
+    \item[\errcode{EINVAL}] O \param{start} non è multiplo di
+      \const{PAGE\_SIZE}, o si è specificato un valore non valido per
+      \param{flags}.
     \item[\errcode{EFAULT}] L'intervallo specificato non ricade in una zona
       precedentemente mappata.
     \end{errlist}
@@ -1365,9 +1386,82 @@ Indicare un intervallo che non contiene pagine mappate non 
 Alla conclusione del processo, ogni pagina mappata verrà automaticamente
 rilasciata, mentre la chiusura del file descriptor usato per effettuare la
 mappatura in memoria non ha alcun effetto sulla stessa.
+
+Infine Linux supporta alcune operazioni specifiche non disponibili su altri
+kernel unix-like. La prima di queste operazioni è la possibilità di modificare
+una mappatura precedente, ad esempio per espanderla o restringerla. Questo è
+realizzato dalla funzione \funcd{mremap}, il cui prototipo è:
+\begin{functions}  
+  \headdecl{unistd.h}
+  \headdecl{sys/mman.h} 
+
+  \funcdecl{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.
+
+  \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}
+    \item[\errcode{EINVAL}] Uno dei puntatori non è validi, in genere si è
+      usato un valore di \param{old\_address} non allineato ad una pagina di
+      memoria.
+    \item[\errcode{EFAULT}] Ci sono degli indirizzi non validi nell'intervallo
+      di memoria specificato dagli argomenti \param{old\_address} e
+      \param{old\_size}, o ci sono altre mappatura di un tipo non
+      corrispondente a quella richiesta.
+    \item[\errcode{ENOMEM}] Non c'è memoria sufficiente oppure l'area di
+      memoria non può essere espansa all'indirizzo virtuale corrente, e non si
+      è specificato \const{MREMAP\_MAYMOVE} nei flag.
+    \item[\errcode{EAGAIN}] Il segmento di memoria scelto è bloccato e non può
+      essere rimappato.
+    \end{errlist}
+  }
+\end{functions}
+
+La funzione richiede come argomenti \param{old\_address} che specifica il
+precedente indirizzo per la mappatura in memoria e \param{old\_size}, che ne
+indica la dimensione, con \param{new\_size} si specifica invece la nuova
+dimensione che si vuole ottenere. Questa funzione usa il meccanismo della
+\index{memoria~virtuale}memoria virtuale per modificare l'associazione fra gli
+indirizzi virtuali del processo e le pagine di memoria, modificando una
+precedente mappatura.
+
+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 \file{sys/mman.h}.}
+che consente di eseguire l'espansione anche quando non è possibile utilizzare
+il predente indirizzo. Per questo motivo la funzione restituisce sempre
+l'indirizzo della nuova zona di memoria, che, se si è usato questo flag, non è
+detto coincida con \param{old\_address}.
+
+La mappatura in memoria di un file viene normalmente eseguita in maniera
+lineare, cioè parti successive di un file vengono mappate linearmente su
+indirizzi successivi in memoria (la prima pagina di un file viene mappata
+sulla prima pagina di 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 parti diverse di un file su
+diverse zone di memoria. 
+
+Questo è ovviamente sempre possibile eseguendo più volte \func{mmap} per
+ciascuna delle diverse aree, ma questo approccio ha delle conseguenze molto
+pesanti in termini di prestazioni. Si ricordi infatti che il \textit{memory
+  mapping} in memoria funziona facendo ricorso al meccaniso della
+\index{memoria~virtuale} memoria virtuale per trascrivere su un file le
+operazioni effettuate sugli indirizzi di memoria sui cui esso è mappato. 
+
+Per questo motivo con il kernel 2.5.46 è stato introdotto ad opera di Ingo
+Molnar un meccanismo che consente la mappatura non lineare, ed i due nuovi
+flag \const{MAP\_POPULATE} e \const{MAP\_NONBLOCK} per \func{mmap}.
+
+
 \itindend{memory~mapping}
 
 
+
 \section{Il file locking}
 \label{sec:file_locking}