I
sistemi operativi – La gestione della memoria
La memoria è una delle tre componenti fondamentali
dell’elaboratore. Essa è direttamente legata alle applicazioni ed ha
rappresentato per molto tempo, per la sua ristrettezza, un problema allo
sviluppo dei sistemi. Le prime memorie erano addirittura fabbricate a mano,
infilando negli anellini di ferrite i fili che servono a portare la corrente
necessaria alla loro magnetizzazione o a leggerne lo stato. Le memorie di tipo
solido, a componenti integrati, appaiono solo agli inizi degli anni 70, e
comunque con una densità ed un costo sempre decisamente elevato.
D’altra parte i programmi, per essere eseguiti, devono essere
caricati completamente in memoria ed
essere accessibili alla CPU. Per di più la portabilità delle applicazioni da un
sistema ad un altro presuppone che i sistemi coinvolti abbiano memoria
sufficiente per poterli contenere. Si è dunque posto il problema di svincolare
le applicazioni dalla dimensione della memoria, quindi di permettere una
portabilità ed uno sviluppo che potesse procedere senza condizionamenti
contingenti. Viene introdotta la cosiddetta “memoria virtuale”.
Se noi analizziamo l’uso che un programma fa della memoria,
possiamo facilmente intuire che non tutte le parti della memoria sono
utilizzate allo stesso modo. Possiamo distinguere in un programma una parte che
serve normalmente ad inizializzare le aree di lavoro ed a stabilire le
connessioni per gli accessi ai dati esterni e che viene eseguita una sola
volta. Vi è poi il ciclo ripetitivo di elaborazione che viene eseguito più
volte, tante quanti sono i dati da trattare ed infine una parte finale,
anch’essa eseguita una sola volta, che chiude l’elaborazione. Nella parte
centrale inoltre vi saranno parti eseguite più frequentemente ed altre meno.
Se noi dividessimo il programma in piccole parti uguali in
dimensione(le chiameremo “pagine”) e ordinassimo queste pagine in funzione
della loro frequenza di accesso, troveremmo per prime alcune pagine con un’alta
frequenza di accesso e via via le altre con una frequenza di accesso sempre
decrescente. Statisticamente possiamo rilevare che per la grande maggioranza
dei programmi abbiamo un addensamento notevole su poche pagine ad alta
frequenza di accesso con un accesso molto basso su un’alta percentuale di
pagine. Il numero delle pagine, o meglio la dimensione delle pagine più
frequentemente accedute si definisce “working set” di un programma.
Ora immaginiamo di poter introdurre una memoria, la memoria
virtuale, che per le applicazioni a
tutti gli effetti possa essere una memoria con un qualcosa che possa mettere a
disposizione della CPU, via via che servono, le pagine di memoria in quel
momento richieste e tenere su un supporto esterno, la memoria ausiliaria (per
esempio un disco), le pagine in quel momento non utilizzate.
Poiché il working set di un programma è più piccolo della
dimensione del programma stesso, questo ci permette di avere una memoria reale
(quella hardware) più piccola di quella virtuale, o meglio, di poter mettere a
disposizione della applicazioni una memoria virtuale più grande di quella
effettivamente installata. Il meccanismo di corrispondenza delle pagine
richiede ovviamente tempo e può essere parte della CPU stessa: in questo caso si
toglie una parte di potenza che potrebbe essere utilizzata per eseguire
istruzioni di programma. Questa potenza è un puro costo e occorre trovare e
realizzare un meccanismo che possa trovare il giusto bilanciamento fra
dimensione della memoria virtuale e memoria reale per ridurre questo spreco al
minimo.
La parte che traduce gli indirizzi da virtuali a reali è quasi
sempre direttamente cablata in circuiti hardware, mentre la parte del sistema
operativo che gestisce la memoria è diventata:
·
Il
gestore della memoria virtuale. Esso ha il compito di gestire l’uso della
memoria assegnandone la proprietà,
gestendo memoria libera ed impegnata.
·
Il
gestore della memoria reale. Questo ha il compito di assegnare, quando
necessario, ad ogni pagina che deve essere caricata in memoria, una
corrispondente parte di memoria reale (frame). Facendo una fotografia
della memoria reale troviamo, l’una accanto all’altra, pagine di programmi
diversi che compongono il working set
delle applicazioni.
·
Il
gestore della memoria ausiliaria. Esso gestisce il trasferimento delle pagine
fra la memoria reale e il supporto esterno su elementi corrispondenti (slot).
Questa attività viene definita “paginazione” e i file esterni utilizzati a
questo scopo sono chiamati appunto “di paginazione” o “di swap”.
All’interno del sistema operativo troviamo un altro supervisore,
il “page supervisor”, che comprende quella parte di logica che deve
eventualmente innescare il processo di paginazione e una serie di componenti
che devono in generale gestire l’ottimizzazione del rapporto fra memoria
virtuale e memoria reale per mantenere la paginazione ad un livello
tollerabile. La paginazione cresce al crescere del rapporto fra memoria
virtuale utilizzata e memoria reale disponibile e lo fa in maniera esponenziale
fino ad arrivare ad un punto in cui il sistema di fatto dedica gran parte delle
sue risorse a questa attività (situazione di “trashing”).
Fortunatamente nel corso degli anni la memoria reale è diventata
sempre meno costosa e sempre più capace, fino ad arrivare oggi ad essere tutto
sommato la parte meno costosa. Di conseguenza la paginazione è scesa in
generale a livelli trascurabili e non rappresenta più l’elemento più critico
per l’ottimizzazione del sistema. Non dimentichiamo però che comunque le
applicazioni sono cresciute in modo considerevole: la funzione di memoria
virtuale è utilizzata normalmente ancora oggi e lo sarà presumibilmente ancora
in futuro. La capacità di indirizzamento virtuale è oggi arrivata a 48 e 63 bit, mentre la memoria reale è
nell’ordine dei 36 bit (decine di Gigabytes): come vedete il divario è ampio e
continuerà ad esserlo ancora per molto.
Nell’equilibrio delle parti oggi torna ad essere delicato il
rapporto fra potenza disponibile e quantità dei dati da gestire, non tanto per
le dimensioni dei supporti esterni disponibili ma soprattutto per la capacità
di accesso ai dati stessi, che, per la maggior parte, risiedono su supporti
esterni e con una velocità di accesso ancora estremamente bassa (circa 6 ordini
di grandezza di differenza fra un supporto di memoria reale e uno di memoria
esterna).
La gestione della memoria esterna sarà l’argomento del prossimo
intervento.
Al Mariani