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).
Errore hardware. Può succedere a te. –