Aggiunte alcune note in piu` sulla memoria virtuale. Introdotto il non-linar
[gapil.git] / fileadv.tex
index 6a94f22492fa08ef6ca8047c9e49681ca23d269d..e5205099135084e515d8568f2a628afb33718bf7 100644 (file)
@@ -998,7 +998,7 @@ si pu
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=13cm]{img/mmap_layout}
+  \includegraphics[width=14cm]{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}
@@ -1038,7 +1038,7 @@ eseguire la mappatura in memoria di un file, 
   \funcdecl{void * mmap(void * start, size\_t length, int prot, int flags, int
     fd, off\_t offset)}
   
-  Esegue la mappatura in memoria del file \param{fd}.
+  Esegue la mappatura in memoria della sezione specificata del file \param{fd}.
   
   \bodydesc{La funzione restituisce il puntatore alla zona di memoria mappata
     in caso di successo, e \const{MAP\_FAILED} (-1) in caso di errore, nel
@@ -1056,11 +1056,18 @@ eseguire la mappatura in memoria di un file, 
       dimensione delle pagine).
     \item[\errcode{ETXTBSY}] Si è impostato \const{MAP\_DENYWRITE} ma
       \param{fd} è aperto in scrittura.
-    \item[\errcode{EAGAIN}] Il file è bloccato, o si è bloccata troppa memoria.
+    \item[\errcode{EAGAIN}] Il file è bloccato, o si è bloccata troppa memoria
+      rispetto a quanto consentito dai limiti di sistema (vedi
+      sez.~\ref{sec:sys_resource_limit}).
     \item[\errcode{ENOMEM}] Non c'è memoria o si è superato il limite sul
       numero di mappature possibili.
     \item[\errcode{ENODEV}] Il filesystem di \param{fd} non supporta il memory
       mapping.
+    \item[\errcode{EPERM}] L'argomento \param{prot} ha richiesto
+      \const{PROT\_EXEC}, ma il filesystem di \param{fd} è montato con
+      l'opzione \texttt{noexec}.
+    \item[\errcode{ENFILE}] Si è superato il limite del sistema sul numero di
+      file aperti (vedi sez.~\ref{sec:sys_resource_limit}).
     \end{errlist}
   }
 \end{functions}
@@ -1213,7 +1220,7 @@ effettive del file o della sezione che si vuole mappare.
 
 \begin{figure}[!htb] 
   \centering
-  \includegraphics[width=10cm]{img/mmap_boundary}
+  \includegraphics[width=12cm]{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}
@@ -1256,7 +1263,7 @@ che sono utilizzabili solo con questa interfaccia.
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=10cm]{img/mmap_exceed}
+  \includegraphics[width=12cm]{img/mmap_exceed}
   \caption{Schema della mappatura in memoria di file di dimensioni inferiori
     alla lunghezza richiesta.}
   \label{fig:file_mmap_exceed}
@@ -1389,14 +1396,15 @@ 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 è:
+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} 
 
   \funcdecl{void * mremap(void *old\_address, size\_t old\_size , size\_t
-    new\_size, unsigned long flags);}
+    new\_size, unsigned long flags)}
   
   Restringe o allarga una mappatura in memoria di un file.
 
@@ -1434,33 +1442,85 @@ 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 è
+il predente indirizzo. Per questo motivo la funzione può restituire un
+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. 
+sulla prima pagina di memoria e così via). 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 la funzione
+\func{mmap} per ciascuna delle diverse aree,\footnote{ed in effetti è quello
+  che veniva fatto prima che fossero introdotte queste estensioni.} ma questo
+approccio ha delle conseguenze molto pesanti in termini di prestazioni. Si
+ricordi infatti che il \textit{memory mapping} funziona facendo ricorso al
+meccanismo della \index{memoria~virtuale} memoria virtuale per trascrivere su
+un file le operazioni effettuate sugli indirizzi di memoria sui cui esso è
+mappato. 
+
+Questo vuol dire che per ciascuna mappatura in memoria deve essere definita
+nella \itindex{page~table} \textit{page table} del processo una nuova area
+della memoria virtuale\footnote{quella che nel gergo del kernel viene chiamata
+  una \textit{virtual memory area} o VMA.} 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-linare si avrà un accrescimento eccessivo della sua \itindex{page~table}
+\textit{page table}, e lo stesso vale per ciascun processo che utilizza questa
+tecnica. In situazioni come questa si possono ottenere peggioramenti notevoli
+delle prestazioni, 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 queste mappature.
 
 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}.
+Molnar un meccanismo che consente la mappatura non lineare, che è una seconda
+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. Questo viene realizzato tramite una nuova system call,
+\funcd{remap\_file\_pages}, il cui prototipo è:
+\begin{functions}  
+  \headdecl{sys/mman.h} 
+
+  \funcdecl{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}.
+
+  \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}] Uno dei puntatori non è validi, in genere si è
+      usato un valore di \param{old\_address} non allineato ad una pagina di
+      memoria.
+    \end{errlist}
+  }
+\end{functions}
+
+
+Insiema al meccanismo per la mappatura non-lineare con sono stati introdotti
+anche due nuovi flag per \func{mmap}: \const{MAP\_POPULATE} e
+\const{MAP\_NONBLOCK}.
 
 
 \itindend{memory~mapping}
 
 
+% i raw device 
+%\subsection{I \textit{raw} device}
+%\label{sec:file_raw_device}
+
+
+
 
 \section{Il file locking}
 \label{sec:file_locking}