+
+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 è:
+\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 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}.
+
+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 è:
+\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}.
+
+