Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
8.5.3. TABELLA DELLE PAGINE INVERTITA
Una tabella delle pagine invertita ha un elemento per ogni pagine reale (o frame). Ciascun
elemento è quindi costituito dell’indirizzo virtuale della pagine memorizzata in quella reale
locazione di memoria, con informazioni sul processo che possiede tale pagina. Quindi, nel sistema
esiste una sola tabella delle pagine che ha un solo elemento per ciascuna pagina di memoria
fisica.
Ciascun indirizzo virtuale è una tripla del tipo seguente:
<id-processo, numero di pagina, scostamento>
Ogni elemento della tabella delle pagine invertita è una coppia <id-processo, numero di pagina>
dove l’id-processo assume il ruolo di identificatore dello spazio d’indirizzi. Quando si fa un
riferimento alla memoria, si presenta una parte dell’indirizzo virtuale, formato da <id-processo,
numero di pagina>, al sottosistema di memoria. Quindi si cerca una corrispondenza nella tabella
delle pagine invertita. Se si trova tale corrispondenza, per esempio sull’elemento i, si genera
l’indirizzo fisico <i, scostamento>. In caso contrario è stato tentato un accesso illegale a un
indirizzo. sebbene questo schema riduca la quantità di memoria necessaria per memorizzare ogni
tabella delle pagine, aumenta però il tempo di ricerca nella tabella quando si fa riferimento a una
pagina. Per limitare l’entità del problema si può impiegare una tabella hash, che riduce la ricerca a
un solo, o a pochi, elementi della tabella delle pagine. Naturalmente, ogni accesso alla tabella
hash aggiunge al procedimento un riferimento alla memoria, quindi un riferimento alla memoria
virtuale richiede almeno due letture della memoria reale: una per l’elemento della tabella hash e
l’altro per la tabella delle pagine. Per migliorare le prestazioni, la ricerca si effettua prima nella TLB,
quindi si consulta la tabella hash.
Nei sistemi che adottano le tabelle delle pagine invertite, l’implementazione della memoria
condivisa è difficoltosa. Una semplice tecnica per superare il problema consiste nel porre nella
tabelle delle pagine una sola associazione fra un indirizzo virtuale e l’indirizzo fisico condiviso; ciò
comporta un errore dovuto all’assenza della pagina per ogni riferimento agli indirizzi virtuali non
associati (page fault).
8.6. SEGMENTAZIONE
Un aspetto importante della gestione della memoria, inevitabile alla presenza della paginazione, è
quello della separazione tra la visione della memoria dell’utente e l’effettiva memoria fisica. Lo
spazio d’indirizzi visto dall’utente non coincide con l’effettiva memoria fisica, ma lo si fa
corrispondere alla memoria fisica. I metodi che stabiliscono questa corrispondenza consentono di
separare la memoria logica dalla memoria fisica.
8.6.1. METODO DI BASE
La tipica struttura di un programma con cui i programmatori hanno familiarità è costituita di una
parte principale e di un gruppo di procedure, funzioni o moduli, insieme con diverse strutture dati
come tabelle, matrici, pile, variabili e cosi via.
La segmentazione è uno schema di gestione della memoria che consente di gestire questa
rappresentazione della memoria dal punto di vista dell’utente. Uno spazio d’indirizzi logici è una
raccolta di segmenti, ciascuno dei quali ha un nome e una lunghezza. Gli indirizzi specificano sia il
nome sia lo scostamento all’interno del segmento, quindi l’utente fornisce ogni indirizzo come una
coppia ordinata di valori: un nome di segmento e uno scostamento. Questo schema contrasta con
la paginazione, in cui l’utente fornisce un indirizzo singolo, che l’architetture di paginazione
suddivide in un numero di pagina e uno scostamento, non visibili al programmatore.
8.6.2. ARCHITETTURA DI SEGMENTAZIONE
Sebbene l’utente possa far riferimento agli oggetti del programma per mezzo di un indirizzo
bidimensionale, la memoria fisica è in ogni caso una sequenza di byte unidimensionale. Per
questo motivo occorre tradurre gli indirizzi bidimensionali definiti dall’utente negli indirizzi fisici
unidimensionali. Questa operazione si compie tramite una tabella dei segmenti; ogni suo elemento
è una coppia ordinata: la base del segmento e il limite del segmento. La base del segmento
contiene l’indirizzo fisico iniziale della memoria dove il segmento risiede, mentre il limite del
segmento contiene la lunghezza del segmento. Un indirizzo logico è formato da due parti: un
numero di segmento s e uno scostamento in tale segmento d. il numero di segmento si usa come
indice per la tabella dei segmenti; lo scostamento d dell’indirizzo logico deve essere compreso tra
0 e il limite del segmento, altrimenti s’invia un segnale di eccezione al sistema operativo.
8. APPROFONDIMENTI SARTIANI
Aspetti importanti del multiplexing:
- Sovrapposizione controllata: stati separati dei thread non dovrebbero collidere in
memoria fisica. Ovviamente, sovrapposizioni inattese causano il caos! Inversamente,
vorremo avere la possibilità di sovrapporli quando desiderato (per la
comunicazione/condivisione).
- Traduzione: Abilità di tradurre accessi da un address space (virtuale) a uno differente
(fisico). In presenza di un meccanismo di traduzione, il processore usa indirizzi virtuali,
mentre la memoria fisica usa indirizzi fisici. Effetti laterali: Può essere usata per evitare
l’overlap; Può essere usata per dare una visione uniforme della memoria ai programmi.
- Protezione: Impedire accessi alla memoria privata di altri processi. A pagine diverse
della memoria può essere dato uno speciale comportamento (sola lettura, invisibili ai
programmi utente, ecc). I dati del kernel protetti dai programmi degli utenti. I programmi
utenti sono protetti da se stessi.
9. MEMORIA VIRTUALE
La memoria virtuale è una tecnica che permette di eseguire processi che possono anche non
essere completamente contenuti in memoria. Il vantaggio principale offerto da questa tecnica è
quello di permettere che i programmi siano più grandi della memoria fisica; inoltre la memoria
virtuale astrae la memoria centrale in un vettore di memorizzazione molto grande e uniforme,
separando la memoria logica, com’è vista dall’utente, da quella fisica. Questa tecnica libera i
programmatori da quel che riguarda i limiti della memoria. La memoria virtuale permette inoltre ai
processi di condividere facilmente file e spazi d’indirizzi, e fornisce un meccanismo efficiente per la
creazione dei processi. La memoria virtuale è però difficile da realizzare e, s’è usata
scorrettamente, può ridurre di molto le prestazioni del sistema.
9.1. INTRODUZIONE
Gli algoritmi di gestione della memoria delineati nel precedente capitolo sono necessari perché,
per l’attivazione di un processo, le istruzioni da eseguire si devono trovare all’interno della
memoria fisica. Il primo metodo per far fronte a tale requisito consiste nel collocare l’intero spazio
d’indirizzi logici del processo relativo in memoria fisica. Il caricamento dinamico può aiutare ad
attenuare gli effetti di tale limitazione, ma richiede generalmente particolari precauzioni e un
ulteriore impegno dei programmatori.
La condizione che le istruzioni debbano essere nella memoria fisica sembra tanto necessaria
quanto ragionevole, ma purtroppo riduce le dimensioni dei programmi a valori strettamente
correlati alle dimensioni della memoria fisica. In effetti, da un esame dei programmi reali risulta che
in molti casi non è necessario avere in memoria l’intero programma; si considerino ad esempio le
seguenti situazioni:
- Spesso i programmi dispongono di codice per la gestione di condizioni di errore insolite.
Poiché questi errori sono rari, se non inesistenti, anche i relativi segmenti di codice non
si eseguono quasi mai.
- Spasso a array, liste e tabelle si assegna più memoria di quanta sia effettivamente
necessaria.
- Alcune opzioni e caratteristiche di un programma sono utilizzabili solo di rado.
Anche nei casi in cui è necessario disporre di tutto il programma è possibile che non serva tutto in
una volta. La possibilità di eseguire un programma che si trova solo parzialmente in memoria può
essere vantaggiosa per i seguenti motivi.
- Un programma non è più vincolato alla quantità di memoria fisica disponibile. Gli utenti
possono scrivere programmi per uno spazio degli indirizzi virtuali molto grande,
semplificando così le operazioni di programmazione;
- Poiché ogni utente impiega meno memoria fisica, si possono eseguire molti più
programmi contemporaneamente, ottenendo un corrispondente aumento dell’utilizzo e
della produttività della CPU senza aumentare il tempo di risposta o di completamento;
- Per caricare (o scaricare) ogni programma utente in memoria sono necessarie meno
operazioni di I/O, quindi ogni programma utente è eseguito più rapidamente.
La possibilità di eseguire un programma che non si trovi completamente in memoria apporterebbe
quindi vantaggi sia al sistema sia all’utente.
La memoria virtuale si fonda sulla separazione della memoria logica percepita dall’utente dalla
memoria fisica. Questa separazione permette di offrire ai programmatori una memoria virtuale
molto ampia, anche se la memoria fisica disponibile è più piccola. La memoria virtuale facilita la
programmazione, poiché il programmatore non deve preoccuparsi della quantità di memoria fisica
disponibile o di quale codice si debba inserire nelle sezioni sovrapponibili, ma può concentrarsi sul
problema da risolvere.
L’espressione spazio degli indirizzi virtuali si riferisce alla collocazione dei processi in memoria
dal punto di vista logico (o virtuale). Da tale punto di vista, un processo inizia in corrispondenza di
un certo indirizzo logico – per esempio, l’indirizzo 0 – e si estende alla memoria contigua, è tuttavia
possibile organizzare la memoria fisica in frame di pagine; in questo caso i frame delle pagine
fisiche assegnati ai processi possono non essere contigui. Spetti all’unità di gestione della
memoria (MMU) associare in memoria le pagine logiche alle pagine fisiche. Si noti come, allo heap
sia lasciato sufficiente spazio per crescere verso l’alto nello spazio di memoria, poiché esso ospita
la memoria allocata dinamicamente. In modo analogo, consentiamo alla pila di svilupparsi verso il
basso nella memoria, a causa di ripetute chiamate di funzione. Lo spazio vuoto ben visibile che
separa lo heap dalla pila è parte dello spazio degli indirizzi virtuali, ma richiede pagine fisiche
realmente esistenti solo nel caso che lo heap o la pila crescano. Oltre a separare la memoria
logica da quella fisica, la memoria virtuale offre, per due o più processi, il vantaggio di c