2011-02-07 9 views
13

Lo spazio di indirizzamento per l'indirizzamento a 64 bit è assolutamente enorme. Ho un programma che sostituirà mmap blocchi di memoria, ciascuno dell'ordine di 100 - 500 MB. Inevitabilmente rimapperò alcune volte, il che potrebbe causare una frammentazione dello spazio contiguo disponibile.In un processo a 64 bit, la mia richiesta mmap/malloc sarà mai negata?

Qualunque frammentazione dello spazio si verifichi, sarà sicuramente banalmente piccolo lo spazio degli indirizzi disponibile.

La mia domanda è: dati questi limiti, in circostanze normali, posso aspettarmi che tutte le richieste mmap abbiano esito positivo (ovvero non esito negativo a causa della frammentazione)? Quali ragioni potrebbero esserci per loro fallendo?

Sono consapevole che l'heap non ha tutto lo spazio a sé, ma immagino abbia la stragrande maggioranza.

Mac OS/Linux.

+2

Errore hardware. Può succedere a te. –

risposta

26

essere consapevoli che la dimensione spazio di indirizzi per "sistemi operativi a 64 bit" non copre necessariamente la gamma a 64 bit completa.

Su x64 (64 bit x86, noto anche come 'AMD64'), ad esempio, l'attuale intervallo di indirizzi virtuali disponibili è "solo" 2x128TB, ovvero 48 bit in due blocchi disgiunti di 47 bit. Su alcuni sistemi SPARC, è 2x2TB, o 2x8TB (41/44 bit). Ciò è dovuto al modo in cui la MMU funziona su queste piattaforme.

Oltre a queste limitazioni architetturali, anche il modo in cui il sistema operativo definisce gli spazi di indirizzamento svolge un ruolo importante.
64bit Windows su x64, ad esempio, limita la dimensione dell'indirizzo virtuale di un'applicazione (anche a 64 bit) a 8 TB (ogni lato utente e kernel 1).

Su sistemi Un * x (tra cui Linux, MacOSX e le * BSD), c'è RLIMIT_AS che si può eseguire una query per via getrlimit(), e - entro limiti specifici del sistema - regolare tramite setrlimit. Il comando ulimit utilizza quelli. Restituiscono/impostano il limite superiore, tuttavia, ovvero lo spazio di indirizzi virtuali totali consentito, inclusi tutti i mapping che un processo può creare (tramite mmap() o il backend malloc, sbrk()). Ma la dimensione totale dello spazio degli indirizzi è diversa dalla dimensione massima di una singola mappatura ...

Dato questo, non è così difficile esaurire lo spazio degli indirizzi virtuali anche su Linux a 64 bit; prova solo, per un test, allo mmap() lo stesso file da 500 GB, diciamo duecento volte. Il mmap fallirà, alla fine.

In breve:

  • mmap() sarà sicuramente fallire una volta che sei fuori di spazio di indirizzamento virtuale. Che è, in qualche modo sorprendentemente, realizzabile su molte architetture "64bit" semplicemente perché gli indirizzi virtuali potrebbero avere meno di 64 bit significativi. L'interruzione esatta dipende dalla CPU e dal sistema operativo in uso e un limite superiore può essere interrogato tramite getrlimit(RLIMIT_AS) o impostato tramite setrlimit(RLIMIT_AS).
  • La frammentazione dello spazio indirizzo può verificarsi a 64 bit utilizzando frequentemente mmap()/munmap() in ordini diversi e con blocchi di dimensioni diverse. Questo alla fine limiterà la dimensione massima che potrai mappare come un singolo pezzo. Prevedere quando esattamente ciò accadrà è difficile poiché dipende sia dalla "cronologia di mappatura" che dall'algoritmo di allocazione dello spazio di indirizzi virtuali dei sistemi operativi. Se ASLR (randomizzazione del layout di spazio degli indirizzi) viene eseguito dal sistema operativo, potrebbe essere imprevedibile nei dettagli e non esattamente riproducibile.
  • malloc() fallirà non oltre il raggiungimento del limite VA totale, su sistemi (come Linux) dove overcommit consente di "chiedere" più memoria di quanta ci sia nel sistema (fisico + swap).
  • On/sistemi operativi macchine dove non overcommit è abilitato, sia malloc() e mmap() con MAP_ANON e/o MAP_PRIVATE mancherà quando + swap fisica è esaurito, perché questi tipi di mapping richiedono memoria di supporto dalla memoria effettiva o swap.

piccolo aggiornamento tecnico: 86 Like e SPARC di cui sopra, il nuovo ARMv8 (64bit ARM, chiamato "AArch64" in Linux) MMU ha anche un "split" spazio per l'indirizzo/un foro spazio di indirizzamento - fuori dal 64 bit in un indirizzo, solo 40 sono rilevanti. Linux dà 39 bit per l'utente, gli indirizzi virtuali 0 ... in poi, 39 bit per il kernel, gli indirizzi virtuali ... 0xFFFFFFFF.FFFFFFFF, quindi il limite è 512 GB (meno quello che è già in uso al momento in cui l'app tenta lo mmap).
Vedere comments here (dalla serie di patch del kernel di abilitazione dell'architettura AArch64).

+2

+1 il tuo rappresentante dovrebbe essere più di 815 con belle risposte come questa. –

+0

Informazioni sulla frammentazione. Ho provato quello che hai detto con 32 file tutti nella dimensione compresa tra 1 e 4 GB, mappandoli e annullandoli in loop su un sistema a 32 bit. A parte un file di 4.0 GB, mmap ha sempre riutilizzato lo stesso indirizzo per ogni file anche se ho passato NULL come parametro per il puntatore richiesto. La frammentazione è visibile solo a 64 bit con i file da 500 GB? – Marenz

+1

per creare la frammentazione dello spazio degli indirizzi tramite 'mmap', eseguire operazioni mappa/non mappatura in ordine diverso e con dimensioni diverse. Cioè dite mmap 1000 file a 1 MB ciascuna, cancellate ogni 3 ° di questo, mmap 150 file da 2 MB ciascuno, cancellate un 20 casuale di questo, ... questo genere di cose. Un semplice ciclo di mmap/munmap sullo stesso set di dati non verrà frammentato (a meno che non sia in uso un algoritmo ASLR molto buggato). Dipende dall'implementazione ASLR se un mmap/munmap/mmap riutilizzerà lo stesso indirizzo o meno (potrebbe, ma se si avvia nuovamente lo stesso programma con un PID diverso, l'indirizzo scelto potrebbe differire). –

0

Basta controllare l'elenco degli errori in man mmap.

+0

Sì, ma di tutti quelli eccetto 'ENOMEM' (e uno o due altri) sono evitabili. Sto chiedendo se '/ perché potrebbe succedere qualcosa come' ENOMEM '. – Joe

+2

Ci può essere un limite sulla quantità di memoria virtuale che un processo può riservare. Vedi 'ulimit -v'. –

8

mmap e malloc potrebbero non riuscire a causa della mancanza di memoria fisica (RAM + swap). In generale, lo standard Unix parla di intervalli di indirizzi "consentiti per lo spazio di indirizzamento di un processo". A parte questo,

Se una funzione essere pubblicizzato per restituire un codice di errore in caso di difficoltà, tu controllare quel codice, sì, anche se i controlli il triplo del tuo codice e produci dolori alle tue dita digitando, per se tu pensi che "non può succedere a me ", gli dei dovranno sicuramente punire te per la tua arroganza .

(Spencer)

+0

Spero non pensiate che non controllerei gli errori! – Joe

+0

@Joe: Buona cosa stai controllando. Ma allora, perché lo stai chiedendo? –

+0

Perché voglio sapere se è probabile che accada mai, e in tal caso, in quali circostanze. – Joe

0

Ebbene, l'OS/C biblioteca è libero di decidere se vi sia memoria sufficiente o meno. Non c'è davvero modo per voi di sapere come lo decide (è ovviamente specifico per il sistema operativo, forse anche sintonizzabile), ma è possibile che ad un certo punto il sistema operativo dica "non di più".

Possibili motivi di errore per allocare la memoria:

  • Linux overcommit di memoria, ma questo è sintonizzabile. A seconda di come è configurato, puoi ottenere ENOMEM non appena superi RAM + Swap.
  • Se i limiti di memoria sono stati impostati utilizzando ulimit, è possibile ottenere ENOMEM anche prima
+0

Qualsiasi sistema Linux configurato correttamente per un utilizzo robusto di server, workstation o in tempo reale avrà l'overcommit disabilitato. L'esecuzione di Linux con overcommit abilitato è molto simile all'esecuzione di Windows 95 ... –

+0

@R: Beh, per quanto ricordo, l'overcommit è attivato di default sotto Linux, quindi immagino che un buon numero di distribuzioni lo invieranno come configurazione di default e quindi alcuni server lo eseguiranno. Può essere problematico, ovviamente. – sleske

+0

So che è attivo per impostazione predefinita. Ma se assumessi amministratori di Linux, assicurandomi che sappiano cos'è l'overcommit e come spegnerlo sarebbe una delle mie prime domande di intervista. :-) –

Problemi correlati