}
\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}
-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}
\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