GNU/Linux >> Linux Esercitazione >  >> Linux

mmap:il file mappato verrà caricato immediatamente in memoria?

Sì, mmap crea una mappatura. Normalmente non legge l'intero contenuto di qualsiasi cosa tu abbia mappato in memoria. Se desideri farlo, puoi usare la chiamata di sistema mlock/mlockall per forzare il kernel a leggere nella RAM il contenuto della mappatura, se applicabile.


No, sì, forse. Dipende.

Chiamando mmap generalmente significa solo che per la tua applicazione, i contenuti del file mappato sono mappati al suo spazio di indirizzi come se il file è stato caricato lì. Oppure, come se il file esistesse davvero in memoria, come se fossero la stessa cosa (che include le modifiche che vengono riscritte sul disco, supponendo che tu abbia accesso in scrittura).

Ne più ne meno. Non ha idea di caricare qualcosa, né l'applicazione sa cosa significa.

Un'applicazione non conosce veramente nulla di simile alla memoria, sebbene il sistema di memoria virtuale la faccia apparire così. La memoria che un'applicazione può "vedere" (e accedere) può corrispondere o meno alla memoria fisica effettiva, e questo può in linea di principio cambiare in qualsiasi momento, senza preavviso e senza una ragione ovvia (ovvia per la tua applicazione).
A parte la possibilità di subire un piccolo ritardo dovuto a un errore di pagina, un'applicazione è (in linea di principio) completamente all'oscuro di qualsiasi cosa del genere accada e ha poco o nessun controllo su di essa.

Le applicazioni, in genere, caricano le pagine dai file mappati (incluso l'eseguibile principale!) su richiesta, come conseguenza dell'incontro con un errore. Tuttavia, un sistema operativo di solito tenta di precaricare speculativamente i dati per ottimizzare le prestazioni.

In pratica, chiamando mmap inizierà immediatamente per precaricare (in modo asincrono) le pagine dall'inizio della mappatura, fino a una certa dimensione specificata dall'implementazione. Il che significa, in linea di principio, che per i file piccoli la risposta sarebbe "sì" e per i file più grandi sarebbe "no".
Tuttavia, mmap non si blocca per attendere il completamento del readahead, il che significa che non hai alcuna garanzia che uno qualsiasi dei file sia nella RAM immediatamente dopo mmap resi (non che tu abbia quella garanzia in qualsiasi momento comunque!). Pertanto, la risposta è "forse".

Sotto Linux, l'ultima volta che ho guardato, la dimensione di precaricamento predefinita era di 31 blocchi (~ 127k) - ma questo potrebbe essere cambiato, inoltre è un parametro regolabile. Man mano che vengono toccate le pagine vicine o alla fine dell'area di precaricamento, più pagine vengono precaricate in modo asincrono.
Se hai accennato a MADV_RANDOM a madvise , il precaricamento è "meno probabile", sotto Linux questo disabilita completamente il precaricamento.

D'altra parte, dando il MADV_SEQUENTIAL hint eseguirà il prefetch in modo asincrono "in modo più aggressivo" a partire dall'inizio della mappatura (e potrebbe scartare le pagine a cui si accede più rapidamente). Sotto Linux, "più aggressivo" significa il doppio della quantità normale.

Dare il MADV_WILLNEED hint suggerisce (ma non garantisce) che tutte le pagine nell'intervallo specificato vengano caricate il prima possibile (poiché stai dicendo che stai per accedervi). Il sistema operativo potrebbe ignorarlo, ma sotto Linux viene trattato piuttosto come un ordine che come un suggerimento, fino al limite RSS massimo del processo e un limite specificato dall'implementazione (se non ricordo male, 1/2 della quantità di RAM fisica ).
Nota che MADV_DONTNEED è probabilmente implementato in modo errato sotto Linux. Il suggerimento non è interpretato nel modo specificato da POSIX, cioè sei d'accordo che le pagine vengano sfogliate per il momento, ma piuttosto che intendi scartarle . Il che non fa una grande differenza per le pagine mappate di sola lettura (a parte un piccolo ritardo, che secondo te andrebbe bene), ma sicuramente conta per tutto il resto.
In particolare, usando MADV_DONTNEED pensare che Linux rilascerà pagine non necessarie dopo che il sistema operativo le ha scritte pigramente su disco non è così che funzionano le cose ! Devi sincronizzare in modo esplicito o prepararti per una sorpresa.

Avendo chiamato readahead sul descrittore di file prima di chiamare mmap (o in alternativa, avendo letto/scritto il file in precedenza), il contenuto del file in pratica infatti essere immediatamente nella RAM.
Questo è, tuttavia, solo un dettaglio di implementazione (sistema di memoria virtuale unificato) e soggetto alla pressione della memoria sul sistema.

Chiamando mlock - supponendo che abbia successo - caricherà immediatamente le pagine richieste nella RAM. Si blocca finché tutte le pagine non sono fisicamente presenti e hai la garanzia che le pagine rimarranno nella RAM finché non le sblocchi.

Esistono funzionalità per interrogare (mincore ) se una o tutte le pagine in un particolare intervallo sono effettivamente presenti al momento e la funzionalità per suggerire al sistema operativo ciò che desideri vedere accadere senza alcuna garanzia (madvise ), e infine la funzionalità per forzare la presenza in memoria di un sottoinsieme limitato di pagine (mlock ) per i processi privilegiati.

Potrebbe non esserlo, sia per mancanza di privilegi che per superamento delle quote o della quantità di RAM fisica presente.


Per impostazione predefinita, mmap() configura solo la mappatura e restituisce (veloce).

Linux (almeno) ha l'opzione MAP_POPULATE (vedi 'man mmap') che fa esattamente ciò di cui tratta la tua domanda.


Linux
  1. Come memorizzare l'output di SHOW PROCESSLIST in un file in MySQL?

  2. Inserimento di un file in un altro file dopo la prima occorrenza di un pattern?

  3. Copiare il contenuto di un file negli appunti senza visualizzarne il contenuto?

  4. Cosa sono la pagina mappata in memoria e la pagina anonima?

  5. L'intero kernel è caricato in memoria all'avvio?

Il Bash '?

Mv Atomic è sulle F?

Output su Stdout e allo stesso tempo Grep in un file?

Come fare eco in un file

Perché le regioni mappate in memoria di sola lettura hanno pagine sporche?

A che serve avere una parte del kernel nello spazio di memoria virtuale dei processi Linux?