Su un'architettura a 32 bit, l'intervallo dello spazio degli indirizzi per l'indirizzamento della RAM è:
0x00000000 - 0xffffffff
o 4'294'967'295
(4GB).
Il kernel linux lo divide 3/1 (potrebbe anche essere 2/2 o 1/3 ) rispettivamente in spazio utente (memoria alta) e spazio kernel (memoria bassa).
L'intervallo dello spazio utente:
0x00000000 - 0xbfffffff
Ogni processo utente appena generato ottiene un indirizzo (intervallo) all'interno di quest'area. I processi utente sono generalmente non attendibili e quindi non possono accedere allo spazio del kernel. Inoltre, sono considerati non urgenti, come regola generale, il kernel cerca di rinviare l'allocazione della memoria a quei processi.
L'intervallo dello spazio del kernel:
0xc0000000 - 0xffffffff
Un processo del kernel ottiene il suo indirizzo (intervallo) qui. Il kernel può accedere direttamente a questo 1 GB di indirizzi (beh, non l'intero 1 GB, ci sono 128 MB riservati per l'accesso ad alta memoria).
I processi generati nello spazio del kernel sono attendibili, urgenti e si presume privi di errori, la richiesta di memoria viene elaborata istantaneamente.
Ogni processo del kernel può anche accedere all'intervallo di spazio utente, se lo desidera. E per ottenere ciò, il kernel mappa un indirizzo dallo spazio utente (la memoria alta) al suo spazio kernel (la memoria bassa), i 128 MB menzionati sopra sono riservati appositamente per questo.
Se la suddivisione è 3/1, 2/2 o 1/3 è controllata dal CONFIG_VMSPLIT_...
opzione; probabilmente puoi controllare sotto /boot/config*
per vedere quale opzione è stata selezionata per il tuo kernel.
Il primo riferimento a cui rivolgersi è Linux Device Drivers (disponibile sia online che in forma di libro), in particolare il capitolo 15 che ha una sezione sull'argomento.
In un mondo ideale, ogni componente del sistema sarebbe in grado di mappare tutta la memoria di cui ha bisogno per accedere. E questo è il caso dei processi su Linux e sulla maggior parte dei sistemi operativi:un processo a 32 bit può accedere solo a poco meno di 2^32 byte di memoria virtuale (in effetti circa 3 GB su una tipica architettura Linux a 32 bit). Diventa difficile per il kernel, che deve essere in grado di mappare l'intera memoria del processo di cui sta eseguendo la chiamata di sistema, più l'intera memoria fisica, più qualsiasi altro dispositivo hardware mappato in memoria.
Pertanto, quando un kernel a 32 bit deve mappare più di 4 GB di memoria, deve essere compilato con un supporto di memoria elevato. La memoria alta è la memoria che non è mappata in modo permanente nello spazio degli indirizzi del kernel. (La memoria insufficiente è l'opposto:è sempre mappata, quindi puoi accedervi nel kernel semplicemente dereferenziando un puntatore.)
Quando accedi alla memoria elevata dal codice del kernel, devi chiamare kmap
prima, per ottenere un puntatore da una struttura dati di pagina (struct page
). Chiamando kmap
funziona se la pagina è in memoria alta o bassa. C'è anche kmap_atomic
che ha aggiunto vincoli ma è più efficiente su macchine multiprocessore perché utilizza un blocco più granulare. Il puntatore ottenuto tramite kmap
è una risorsa:utilizza lo spazio degli indirizzi. Una volta terminato, devi chiamare kunmap
(o kunmap_atomic
) per liberare tale risorsa; quindi il puntatore non è più valido e non è possibile accedere al contenuto della pagina finché non si chiama kmap
di nuovo.
Questo è rilevante per il kernel Linux; Non sono sicuro di come qualsiasi kernel Unix gestisca questo.
La memoria alta è il segmento di memoria che i programmi in spazio utente possono indirizzare. Non può toccare Memoria insufficiente.
Low Memory è il segmento di memoria che il kernel Linux può indirizzare direttamente. Se il kernel deve accedere alla memoria elevata, deve prima mapparla nel proprio spazio di indirizzi.
Di recente è stata introdotta una patch che ti consente di controllare dove si trova il segmento. Il compromesso è che puoi togliere la memoria indirizzabile dallo spazio utente in modo che il kernel possa avere più memoria che non deve mappare prima dell'uso.
Risorse aggiuntive:
- http://tldp.org/HOWTO/KernelAnalysis-HOWTO-7.html
- http://linux-mm.org/HighMemory