+ \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}.
+
+ \bodydesc{La funzione restituisce il puntatore alla zona di memoria mappata
+ in caso di successo, e \macro{MAP\_FAILED} (-1) in caso di errore, nel
+ qual caso \var{errno} viene impostata ai valori:
+ \begin{errlist}
+ \item[\macro{EBADF}] Il file descriptor non è valido, e non si è usato
+ \macro{MAP\_ANONYMOUS}.
+ \item[\macro{EACCES}] Il file descriptor non si riferisce ad un file
+ regolare, o si è richiesto \macro{MAP\_PRIVATE} ma \param{fd} non è
+ aperto in lettura, o si è richiesto \macro{MAP\_SHARED} e impostato
+ \macro{PROT\_WRITE} ed \param{fd} non è aperto in lettura/scrittura, o
+ si è impostato \macro{PROT\_WRITE} ed \param{fd} è in
+ \textit{append-only}.
+ \item[\macro{EINVAL}] I valori di \param{start}, \param{length} o
+ \param{offset} non sono validi (o troppo grandi o non allineati sulla
+ dimensione delle pagine).
+ \item[\macro{ETXTBSY}] Si è impostato \macro{MAP\_DENYWRITE} ma \param{fd}
+ è aperto in scrittura.
+ \item[\macro{EAGAIN}] Il file è bloccato, o si è bloccata troppa memoria.
+ \item[\macro{ENOMEM}] Non c'è memoria o si è superato il limite sul numero
+ di mappature possibili.
+ \item[\macro{ENODEV}] Il filesystem di \param{fd} no supporta il memory
+ mapping.
+ \end{errlist}
+ }
+\end{functions}
+
+La funzione richiede di mappare in memoria la sezione del file \param{fd} a
+partire da \param{offset} per \param{lenght} byte, preferibilmente
+all'indirizzo \param{start}. Il valore di \param{offset} deve essere un
+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 \macro{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 \tabref{tab:file_mmap_flag}; il valore
+specificato deve essere compatibile con la modalità con cui si è aperto il
+file.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \macro{PROT\_EXEC} & Le pagine possono essere eseguite.\\
+ \macro{PROT\_READ} & Le pagine possono essere lette.\\
+ \macro{PROT\_WRITE} & Le pagine possono essere scritte.\\
+ \macro{PROT\_NONE} & L'accesso alle pagine è vietato.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{prot} di \func{mmap}, relativi alla
+ protezione applicate alle pagine del file mappate in memoria.}
+ \label{tab:file_mmap_prot}
+\end{table}
+
+L'argomento \param{flags} specifica qual'è il tipo di oggetto mappato, le
+opzioni relative alle modalità con cui è effettuata la mappatura e alle
+modalità con cui le modifiche alla memoria mappata vengono condivise o
+mantenute private al processo che le ha effettuate. Deve essere specificato
+come maschera binaria ottenuta dall'OR di uno o più dei valori riportati in
+\tabref{tab:file_mmap_flag}.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|p{10cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \macro{MAP\_FIXED} & Non permette di restituire un indirizzo diverso
+ da \param{start}, se questo non può essere usato
+ \func{mmap} fallisce. Se si imposta questo flag il
+ valore di \param{start} deve essere allineato
+ alle dimensioni di una pagina. \\
+ \macro{MAP\_SHARED} & I cambiamenti sulla memoria mappata vengono
+ riportati sul file e saranno immediatamente
+ visibili agli altri processi che mappano lo stesso
+ file.\footnotemark Il file su disco però non sarà
+ aggiornato fino alla chiamata di \func{msync} o
+ \func{unmap}), e solo allora le modifiche saranno
+ visibili per l'I/O convenzionale. Incompatibile
+ con \macro{MAP\_PRIVATE}. \\
+ \macro{MAP\_PRIVATE} & I cambiamenti sulla memoria mappata non vengono
+ riportati sul file. Ne viene fatta una copia
+ privata cui solo il processo chiamante ha
+ accesso. Le modifiche sono mantenute attraverso
+ il meccanismo del \textit{copy on write} e
+ salvate su swap in caso di necessità. Non è
+ specificato se i cambiamenti sul file originale
+ vengano riportati sulla regione
+ mappata. Incompatibile con \macro{MAP\_SHARED}. \\
+ \macro{MAP\_DENYWRITE} & In Linux viene ignorato per evitare
+ \textit{DoS}\index{DoS} (veniva usato per
+ segnalare che tentativi di scrittura sul file
+ dovevano fallire con \macro{ETXTBUSY}).\\
+ \macro{MAP\_EXECUTABLE}& Ignorato. \\
+ \macro{MAP\_NORESERVE} & Si usa con \macro{MAP\_PRIVATE}. Non riserva
+ delle pagine di swap ad uso del meccanismo di
+ \textit{copy on write} per mantenere le
+ modifiche fatte alla regione mappata, in
+ questo caso dopo una scrittura, se non c'è più
+ memoria disponibile, si ha l'emissione di
+ un \macro{SIGSEGV}. \\
+ \macro{MAP\_LOCKED} & Se impostato impedisce lo swapping delle pagine
+ mappate. \\
+ \macro{MAP\_GROWSDOWN} & Usato per gli stack. Indica
+ che la mappatura deve essere effettuata con gli
+ indirizzi crecenti verso il basso.\\
+ \macro{MAP\_ANONYMOUS} & La mappatura non è associata a nessun file. Gli
+ argomenti \param{fd} e \param{offset} sono
+ ignorati.\footnotemark\\
+ \macro{MAP\_ANON} & Sinonimo di \macro{MAP\_ANONYMOUS}, deprecato.\\
+ \macro{MAP\_FILE} & Valore di compatibiità, deprecato.\\
+ \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 \macro{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
+tutto quanto è comunque basato sul basato sul meccanismo della memoria
+virtuale. Questo comporta allora una serie di conseguenze. La più ovvia è che
+se si cerca di scrivere su una zona mappata in sola lettura si avrà
+l'emissione di un segnale di \macro{SIGSEGV}, dato che i permessi sul segmento
+di memoria relativo non consentono questo tipo di accesso.
+
+È invece assai più complessa la questione relativa agli accessi al di fuori
+della regione di cui si è richiesta la mappatura. In generale infatti si è
+portati a ritenere che anch'essi dovrebbero dar luogo all'emissione di un
+segnale di \macro{SIGSEGV}; questo però non tiene conto del fatto che essendo
+basata sul meccanismo della paginazione, una mappatura non può che essere
+eseguita su un segmento di memoria di dimensioni uguali ad un multiplo di
+quelle di una pagina. In generale dette dimensioni potranno non corrispondere
+alle dimensioni effettive del file o della sezione che si vuole mappare. Il
+caso più comune che si presenta è quello illustrato in
+\figref{fig:file_mmap_boundary}, in cui la sezione di file non rientra nei
+confini di una pagina: in tal caso verrà mappato su un segmento di memoria che
+si estende fino al bordo della pagina successiva.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=10cm]{img/mmap_boundary}
+ \caption{Schema della mappatura in memoria di una sezione di file di
+ dimensioni non corripondenti al bordo di una pagina.}
+ \label{fig:file_mmap_boundary}
+\end{figure}
+
+Si ha così una situazione in cui sarà possibile accedere, senza ottenere un
+\macro{SIGSEGV}, a quella zona di memoria che eccede le dimensioni specificate
+da \param{lenght}, dato che essa è presente nello spazio di indirizzi del
+processo, anche se non è mappata sul file. In questo caso quello che succede è
+che gli accessi in lettura restituiranno dei valori nulli, mentre gli accessi
+in scrittura non avranno alcun effetto e non saranno scritti sul file.
+
+Un caso più complesso è quello illustrato in \figref{fig:file_mmap_exceed},
+che avviene quando le dimensioni del file sono più corte di quelle su cui si
+vuole effettuare la mappatura, oppure quando il file è stato troncato da un
+altro processo ad una dimensione inferiore.
+
+\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 tal caso per la parte del file esistente vale esattamente quanto detto in
+precedenza, mentre per la parte di memoria che eccede il bordo della pagina,
+ma inferiore alle dimensioni richiete con \param{length}, si avrà il segnale
+\macro{SIGBUS}.
+
+Si tenga presente che non tutti i file possono venire mappati in memoria, la
+mappatura infatti introduce una corrispondenza biunivoca fra una sezione di un
+file ed una sezione di memoria, pertanto si può parlare tanto di file mappato
+in memoria, quanto di memoria mappata su file. Questo comporta che ad esempio
+non è possibile mappare in memoria pipe, socket e fifo, per le quali non ha
+senso parlare di \textsl{sezione}. Lo stesso vale anche per alcuni file di
+dispositivo, che non dispongono della relativa operazione \var{mmap} (si
+ricordi quanto esposto in \secref{sec:file_vfs_work}), ma esistono anche casi
+(un esempio è l'interfaccia ponte PCI-VME del chip Universe) di dispositivi
+che sono utilizzabili praticamente solo con questa interfaccia.
+
+Dato che passando attraverso una \func{fork} lo spazio di indirizzi viene
+copiato, i file mappati in memoria verranno ereditati in maniera trasparente
+dal processo figlio, mantenendo gli stessi attributi avuti nel padre; così se
+si è usato \macro{MAP\_SHARED} padre e figlio accederanno allo stesso file in
+maniera condivisa, mentre se si è usato \macro{MAP\_PRIVATE} ciascuno di essi
+manterrà una sua versione privata indipendente. Non c'è invece nessun
+passaggio attraverso una \func{exec}, dato che quest'ultima sostituisce tutto
+lo spazio degli indirizzi di un processo con quello di un nuovo programma.
+
+Quando si effettua la mappatura di un file vengono pure modificati i tempi ad
+esso associati (si ricordi quanto esposto in \secref{sec:file_file_times}). Il
+valore di \var{st\_atime} può venir cambiato in qualunque istante a partire
+dal momento in cui la mappatura è stata effettuata: il primo riferimento ad
+una pagina mappata su un file aggiorna questo tempo. I valori di
+\var{st\_ctime} e \var{st\_mtime} possono venir cambiati solo quando si è
+consentita la scrittura sul file (cioè per un file mappato con
+\macro{PROT\_WRITE} e \macro{MAP\_SHARED}) e sono aggiornati dopo la scrittura
+o in corrispondenza di una eventuale \func{msync}.
+
+Dato per i file mappati in memoria le operazioni di I/O sono gestite
+direttamente dalla memoria virtuale, occorre essere consapevoli delle
+interazioni che possono esserci con operazioni effettuate con l'interfaccia
+standard dei file di \capref{sec:file_unix_interface}. Il problema è che una
+volta che si è mappato un file, le operazioni di lettura e scrittura saranno
+eseguite sulla memoria, e riportate su disco in maniera autonoma dal sistema
+della memoria virtuale.
+
+Pertanto se si modifica un file con l'interfaccia standard queste modifiche
+potranno essere visibili o meno a seconda del momento in cui la memoria
+virtuale leggerà dal disco in memoria quella sezione del file, perciò è del
+tutto indefinito il risultato della modifica nei confronti del contenuto della
+memoria mappata.
+
+Se è, per quanto appena visto, sconsigliabile eseguire scritture su file
+attraverso l'interfaccia standard quando lo si è mappato in memoria, è invece
+possibile usare l'interfaccia standard per leggere un file mappato in memoria,
+purché si abbia una certa cura; infatti l'interfaccia dell'I/O mappato in
+memoria mette a disposizione la funzione \func{msync} per sincronizzare il
+contenuto della memoria mappata con il file su disco; il suo prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{sys/mman.h}
+
+ \funcdecl{int msync(const void *start, size\_t length, int flags)}
+
+ Sincronizza i contenuti di una sezione di un file mappato in memoria.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
+ errore nel qual caso \var{errno} viene impostata ai valori:
+ \begin{errlist}
+ \item[\macro{EINVAL}] O \param{start} non è multiplo di \macro{PAGESIZE},
+ o si è specificato un valore non valido per \param{flags}.
+ \item[\macro{EFAULT}] L'intervallo specificato non ricade in una zona
+ precedentemente mappata.
+ \end{errlist}
+ }
+\end{functions}
+
+La funzione esegue la sincronizzazione di quanto scritto nella sezione di
+memoria indicata da \param{start} e \param{offset}, scrivendo le modifiche sul
+file (qualora questo non sia già stato fatto). Provvede anche ad aggiornare i
+relativi tempi di modifica. In questo modo si è sicuri che dopo l'esecuzione
+di \func{msync} le funzioni dell'interfaccia standard troveranno un contenuto
+del file aggiornato.
+
+L'argomento \param{flag} è specificato come maschera binaria composta da un OR
+dei valori riportati in \tabref{tab:file_mmap_rsync}, di questi però
+\macro{MS\_ASYNC} e \macro{MS\_SYNC} sono incompatibili; con il primo valore
+infatti la funzione si limita ad inoltrare la richiesta di sincronizzazione al
+meccanismo della memoria virtuale, ritornando subito, mentre con il secondo
+attende che la sincronizzazione sia stata effettivamente eseguita. Il terzo
+flag fa invalidare le pagine di cui si richiede la sincronizzazione per tutte
+le mappature dello stesso file, così che esse possano essere immediatamente
+aggiornate ai nuovi valori.
+
+\begin{table}[htb]
+ \centering
+ \footnotesize
+ \begin{tabular}[c]{|l|l|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \macro{MS\_ASYNC} & Richiede la sincronizzazione.\\
+ \macro{MS\_SYNC} & Attende che la sincronizzazione si eseguita.\\
+ \macro{MS\_INVALIDATE}& Richiede che le altre mappature dello stesso file
+ siano invalidate.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dell'argomento \param{flag} di \func{msync}.}
+ \label{tab:file_mmap_rsync}
+\end{table}
+
+Una volta che si sono completate le operazioni di I/O si può eliminare la
+mappatura della memoria usando la funzione \func{munmap}, il suo prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{sys/mman.h}
+
+ \funcdecl{int munmap(void *start, size\_t length)}
+
+ Rilascia la mappatura sulla sezione di memoria specificata.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo, e -1 in caso di
+ errore nel qual caso \var{errno} viene impostata ai valori:
+ \begin{errlist}
+ \item[\macro{EINVAL}] L'intervallo specificato non ricade in una zona
+ precedentemente mappata.
+ \end{errlist}
+ }
+\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.
+
+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.