Inserita mprotect, che mancava dalle funzioni per la gestione del memory
authorSimone Piccardi <piccardi@gnulinux.it>
Sun, 26 Jun 2005 01:14:15 +0000 (01:14 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Sun, 26 Jun 2005 01:14:15 +0000 (01:14 +0000)
mapping, e iniziato a ddescrivere remap_file_pages.

fileadv.tex

index e5205099135084e515d8568f2a628afb33718bf7..f7fba16f329e1116e2f3d44123f7d51635667b7b 100644 (file)
@@ -1383,22 +1383,60 @@ mappatura della memoria usando la funzione \funcd{munmap}, il suo prototipo 
   }
 \end{functions}
 
-La funzione cancella la mappatura per l'intervallo specificato attraverso
-\param{start} e \param{length}, ed ogni successivo accesso a tale regione
-causerà un errore di accesso in memoria. L'argomento \param{start} deve essere
-allineato alle dimensioni di una pagina di memoria, e la mappatura di tutte le
-pagine contenute (anche parzialmente) nell'intervallo indicato, verrà rimossa.
-Indicare un intervallo che non contiene pagine mappate non è un errore.
+La funzione cancella la mappatura per l'intervallo specificato con
+\param{start} e \param{length}; ogni successivo accesso a tale regione causerà
+un errore di accesso in memoria. L'argomento \param{start} deve essere
+allineato alle dimensioni di una pagina, e la mappatura di tutte le pagine
+contenute anche parzialmente nell'intervallo indicato, verrà rimossa.
+Indicare un intervallo che non contiene mappature non è un errore.  Si tenga
+presente inoltre che alla conclusione di un processo ogni pagina mappata verrà
+automaticamente rilasciata, mentre la chiusura del file descriptor usato per
+il \textit{memory mapping} non ha alcun effetto su di esso.
+
+Lo standard POSIX prevede anche una funzione che permetta di cambiare le
+protezioni delle pagine di memoria; lo standard prevede che essa si applichi
+solo ai \textit{memory mapping} creati con \func{mmap}, ma nel caso di Linux
+la funzione può essere usata con qualunque pagina valida nella memoria
+virtuale. Questa funzione è \funcd{mprotect} ed il suo prototipo è:
+\begin{functions}  
+%  \headdecl{unistd.h}
+  \headdecl{sys/mman.h} 
+
+  \funcdecl{int mprotect(const void *addr, size\_t len, int prot)}
+  
+  Modifica le protezioni delle pagine di memoria comprese nell'intervallo
+  specificato.
+
+  \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}] il valore di \param{addr} non è valido o non è un
+      multiplo di \const{PAGE\_SIZE}.
+    \item[\errcode{EACCESS}] l'operazione non è consentita, ad esempio si è
+      cercato di marcare con \const{PROT\_WRITE} un segmento di memoria cui si
+      ha solo accesso in lettura.
+%     \item[\errcode{ENOMEM}] non è stato possibile allocare le risorse
+%       necessarie all'interno del kernel.
+%     \item[\errcode{EFAULT}] si è specificato un indirizzo di memoria non
+%       accessibile.
+    \end{errlist}
+    ed inoltre \errval{ENOMEM} ed \errval{EFAULT}.
+  } 
+\end{functions}
+
+
+La funzione prende come argomenti un indirizzo di partenza in \param{addr},
+allineato alle dimensioni delle pagine di memoria, ed una dimensione
+\param{size}. La nuova protezione deve essere specificata in \param{prot} con
+una combinazione dei valori di tab.~\ref{tab:file_mmap_prot}.  La nuova
+protezione verrà applicata a tutte le pagine contenute, anche parzialmente,
+dall'intervallo fra \param{addr} e \param{addr}+\param{size}-1.
 
-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
-un precedente \textit{memory mapping}, ad esempio per espanderlo o
-restringerlo. Questo è realizzato dalla funzione \funcd{mremap}, il cui
-prototipo è:
+kernel unix-like. La prima di queste è la possibilità di modificare 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} 
@@ -1413,81 +1451,78 @@ prototipo 
       -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
+    \item[\errcode{EINVAL}] il valore di \param{old\_address} non è un
+      puntatore valido.
+    \item[\errcode{EFAULT}] ci sono indirizzi non validi nell'intervallo
+      specificato da \param{old\_address} e \param{old\_size}, o ci sono altre
+      mappature di 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ò
+    \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 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 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}.
+La funzione richiede come argomenti \param{old\_address} (che deve essere
+allineato alle dimensioni di una pagina di memoria) che specifica il
+precedente indirizzo del \textit{memory mapping} e \param{old\_size}, che ne
+indica la dimensione. Con \param{new\_size} si specifica invece la nuova
+dimensione che si vuole ottenere. 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 precedente indirizzo. Per questo
+motivo, se si è usato questo flag, la funzione può restituire un indirizzo
+della nuova zona di memoria che non è detto coincida con \param{old\_address}.
+
+La funzione si appoggia al sistema della \index{memoria~virtuale} memoria
+virtuale per modificare l'associazione fra gli indirizzi virtuali del processo
+e le pagine di memoria, modificando i dati direttamente nella
+\itindex{page~table} \textit{page table} del processo. Come per
+\func{mprotect} la funzione può essere usata in generale, anche per pagine di
+memoria non corrispondenti ad un \textit{memory mapping}, e consente così di
+implementare la funzione \func{realloc} in maniera molto efficiente.
+
+Una caratteristica comune a tutti i sistemi unix-like è che la mappatura in
+memoria di un file viene eseguita in maniera lineare, cioè parti successive di
+un file vengono mappate linearmente su indirizzi successivi in 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 sezioni diverse di un file su diverse zone di memoria.
+
+Questo è ovviamente sempre possibile eseguendo la funzione \func{mmap} per
+ciascuna delle diverse aree,\footnote{ed in effetti è quello che veniva fatto
+  anche con Linux prima che fossero introdotte queste estensioni.} ma questo
+approccio ha delle conseguenze molto pesanti in termini di prestazioni.
+Infatti per ciascuna mappatura in memoria deve essere definita nella
+\itindex{page~table} \textit{page table} del processo una nuova area di
+memoria virtuale\footnote{quella che nel gergo del kernel viene chiamata VMA
+  (\textit{virtual memory area}).} 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, 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 è:
+\textit{page table}, e lo stesso accadrà per tutti gli altri processi che
+utilizzano questa tecnica. In situazioni in cui le applicazioni hanno queste
+esigenze si avranno delle prestazioni ridotte, 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 una gran quantità di
+\textit{memory mapping}.
+
+Per questo motivo con il kernel 2.5.46 è stato introdotto, ad opera di Ingo
+Molnar, un meccanismo che consente la mappatura non-lineare. Anche questa è
+una 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. Ciò è possibile grazie ad una
+nuova system call, \funcd{remap\_file\_pages}, il cui prototipo è:
 \begin{functions}  
   \headdecl{sys/mman.h} 
 
@@ -1499,13 +1534,24 @@ questa i dati del file. Questo viene realizzato tramite una nuova system call,
   \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.
+    \item[\errcode{EINVAL}] Si è usato un valore non valido per uno degli
+      argomenti o \param{start} non fa riferimento ad un \textit{memory
+        mapping} valido creato con \const{MAP\_SHARED}.
     \end{errlist}
   }
 \end{functions}
 
+Per poter utilizzare questa funzione occorre anzitutto effettuare
+preliminarmente una chiamata a \func{mmap} con \const{MAP\_SHARED} per
+definire l'area di memoria che poi sarà rimappata non linearmente. Poi di
+chiamerà questa funzione per modificare le corrispondenze fra pagine di
+memoria e pagine del file; si tenga presente che \func{remap\_file\_pages}
+permette anche di mappare la stessa pagina di un file in più pagine della
+regione mappata.
+
+La funzione richiede che si identifichi la pagine di file che si vuole
+rimappare con \param{pgoff} e \param{size}, che ne indicano l'inizio (in unità
+della dimensione delle pagine di memoria) \param{start}
 
 Insiema al meccanismo per la mappatura non-lineare con sono stati introdotti
 anche due nuovi flag per \func{mmap}: \const{MAP\_POPULATE} e