Vai al contenuto
Sistemi di Elaborazione

Memoria virtuale: pagine, tabella delle pagine e TLB

Indirizzi virtuali e fisici, protezione e condivisione, tabella delle pagine a più livelli, TLB, page fault, thrashing, copy-on-write e microcontrollori.

Sul computer girano insieme decine di programmi, e ognuno si comporta come se avesse tutta la memoria per sé, a partire dall’indirizzo zero, senza poter leggere o rovinare quella degli altri. È l’effetto della memoria virtuale: gli indirizzi usati dai programmi non sono quelli fisici della DRAM, ma vengono tradotti dall’hardware a ogni accesso, sotto il controllo del sistema operativo. In questa lezione vediamo le pagine, la tabella delle pagine, il TLB e cosa succede quando un dato non è in memoria.

Indirizzi virtuali e fisici

Lo spazio degli indirizzi virtuali di ogni processo e la memoria fisica sono divisi in blocchi di uguale dimensione: le pagine (tipicamente 4 KiB). Un indirizzo virtuale si divide in

  • il numero di pagina virtuale (VPN), i bit alti;
  • l’offset nella pagina, i 12 bit bassi (2^{12} = 4096).

La traduzione sostituisce il numero di pagina virtuale con un numero di pagina fisica (PPN) e lascia invariato l’offset.

Traduzione di un indirizzo virtuale in fisico con il TLB e la tabella delle pagine
L’indirizzo virtuale è diviso in numero di pagina virtuale e offset. Il numero di pagina si cerca prima nel TLB e, se non c’è, nella tabella delle pagine; il risultato è il numero di pagina fisica, che affiancato all’offset invariato forma l’indirizzo fisico.

Cosa si ottiene

  • Isolamento e protezione: ogni processo ha la sua tabella, e non può nemmeno nominare le pagine degli altri. Ogni voce ha dei permessi (lettura, scrittura, esecuzione, accesso solo per il sistema operativo): scrivere su una pagina di codice o leggere una pagina del kernel produce un’eccezione.
  • Memoria contigua apparente: un vettore di 1 MiB è contiguo negli indirizzi virtuali anche se le sue pagine fisiche sono sparse.
  • Condivisione: le librerie usate da molti programmi stanno in memoria una volta sola, mappate negli spazi virtuali di tutti.
  • Più memoria di quella fisica: le pagine usate poco possono stare su disco e tornare in memoria quando servono.

La tabella delle pagine

Il sistema operativo mantiene per ogni processo una tabella delle pagine in memoria: per ogni pagina virtuale, se è presente in memoria, il numero di pagina fisica e i permessi.

Il problema della dimensione. Con indirizzi virtuali a 48 bit e pagine da 4 KiB ci sono 2^{36} pagine virtuali; una tabella piatta con voci da 8 byte occuperebbe 2^{36}\cdot 8 = 512 GiB per processo. Ma un processo usa solo una piccola parte del suo spazio. Si usano allora tabelle a più livelli (quattro nei processori x86 e ARM a 64 bit): il numero di pagina si divide in quattro gruppi di 9 bit, ognuno indice di una tabella di 512 voci che punta alla tabella del livello successivo, e le tabelle delle zone non usate non esistono proprio.

Il TLB

Così, però, ogni accesso alla memoria ne richiederebbe altri quattro per percorrere le tabelle. La soluzione è una piccola cache dedicata alle traduzioni, il TLB (Translation Lookaside Buffer), con qualche decina o centinaio di voci associative. Grazie alla località, oltre il 99% delle traduzioni lo trova già lì. Solo in caso di fallimento l’hardware (o il sistema operativo, in alcune architetture) percorre le tabelle e carica la voce nel TLB.

Quando il sistema operativo passa da un processo all’altro cambia la tabella delle pagine attiva (un registro che ne contiene l’indirizzo), e le voci del TLB del processo precedente non devono essere usate: o si svuota il TLB, o ogni voce porta un identificatore del processo.

Il page fault

Se la voce della tabella indica che la pagina non è in memoria, l’hardware genera un’eccezione, il page fault, e passa il controllo al sistema operativo, che:

  1. trova una pagina fisica libera, o ne libera una scrivendo su disco una pagina poco usata (se è stata modificata);
  2. legge dal disco la pagina richiesta;
  3. aggiorna la tabella e riprende l’istruzione interrotta, che questa volta riesce.

Leggere da un SSD richiede circa 100 µs, centinaia di migliaia di cicli di clock: un page fault ogni tanto non si nota, ma se i programmi usano più memoria di quella fisica e le pagine vengono continuamente scambiate con il disco (thrashing) il sistema diventa lentissimo.

Lo stesso meccanismo, usato apposta, permette trucchi molto utili: le pagine di un file aperto vengono caricate solo quando si leggono (file mappati in memoria); dopo una fork() padre e figlio condividono le pagine finché uno dei due non ne scrive una, e solo allora viene copiata (copy-on-write).

E nei microcontrollori?

I microcontrollori piccoli non hanno memoria virtuale: un solo programma, indirizzi fisici, e al più un’unità di protezione della memoria (MPU) che vieta l’accesso ad alcune zone. La memoria virtuale serve dove girano più programmi non fidati insieme, cioè nei sistemi con un sistema operativo completo come Linux, Windows, Android.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x
()
x