vuoi
o PayPal
tutte le volte che vuoi
COLLEGAMENTO DINAMICO E LIBRERIE CONDIVISE
Il funzionamento del collegamento dinamico è analogo a quello del caricamento, ma si riferisce
appunto al collegamento delle librerie.
Questo metodo si utilizza soprattutto per le librerie di sistema.
In ogni programma è presente una porzione di codice, detta stub, che indica come localizzare la
procedura di libreria o come caricare la libreria stessa se non è presente.
Il collegamento dinamico vale anche per gli aggiornamenti delle librerie. Una libreria vecchia può
essere sostituita dalla nuova e tutti i programmi che fanno riferimento alla vecchia usano
automaticamente quella nuova. Questo sistema è chiamato librerie condivise.
Al contrario del caricamento dinamico, il collegamento necessita dell’intervento da parte del SO, in
quanto solo quest’ultimo ha i permessi di controllare se la procedra richiesta è presente nello spazio
di memoria di un altro processo, o di consentire l’accesso allo stesso indirizzo di memoria a più
processi.
AVVICENDAMENTO (SWAPPING) DEI PROCESSI
Per definire lo swapping dei processi si può prendere come esempio l’algoritmo di scheduling
round-robin. Non appena è trascorso il quanto di tempo del processo in esecuzione, il quale deve
avere una durata tale che sia eseguito un numero ragionevole di operazioni, il gestore della memoria
scarica dalla memoria il processo appena terminato e carica nello spazio lasciato libero un nuovo
processo. Questa operazione determina un avvicendamento (o scambio) di processi e, nel frattempo,
la CPU assegna un quanto di tempo ad un altro processo.
Vi è però una limitazione causata
dall’associazione degli indirizzi. Infatti, se
l’associazione è avvenuta nella fase di
assemblaggio o di caricamento, allora il
processo non può essere ricaricato in
posizioni diverse, mentre, se è avvenuta nella
fase di esecuzione, allora il processo può
essere caricato in uno spazio diverso.
Inoltre lo swapping richiede la presenza di
una memoria ausiliaria, la quale dev’essere
abbastanza ampia in modo da contenere la
copia di tutte le immagini di memoria di tutti i
processi utente, e deve garantire un accesso
diretto ad esse.
Lo swapping è vincolato anche dal fatto che, prima di scaricare un processo dalla memoria, bisogna
assicurarsi che esso sia completamente terminato. Infatti è possibile che un processo sia in attesa di
un’operazione I/O. Questa operazione I/O potrebbe rischiare di utilizzare la memoria del processo
che si avvicenda a quello correntemente in attesa. Si può risolvere in due modi:
1. non si sostiuiscono processi che hanno operazioni I/O pendenti;
2. eseguendo operazioni I/O solo nella memoria I/O del sistema operativo.
ALLOCAZIONE CONTIGUA E METODO DELLE PARTIZIONI MULTIPLE
La memoria centrale è formata da due partizioni, una per il sistema operativo e l’altra per i processi
utente. Il sistema operativo può trovarsi sia in memoria alta che bassa, ma essendo il vettore delle
interruzioni posizionato in memoria bassa allora si suppone che lo sia anche il SO.
Generalmente, si vuole che in memoria centrale siano presenti più processi utente, perciò è
necessario stabilire come viene assegnata la memoria disponibile ai vari processi presenti nella coda
d’ingresso. Mediante l’allocazione contingua si fa in modo che ogni processo sia contenuto in una
singola sezione di memoria.
Un modo per suddividere la memoria può essere quello di creare delle partizioni aventi dimensione
fissa, ognuna delle quali deve contenere un unico processo.
Nel metodo della partizioni multiple (MVT) il grado di multiprogrammazione è quindi
influenzato dal numero di partizioni.
Il funzionamento è il seguente: quando una partizione è libera può essere occupata da un processo
presente nella coda d’ingresso, e risulta essere nuovamente libera una volta che il processo termina.
Il SO mantiene una tabella in cui vi sono le partizioni disponibili e quelle occupate e, inizialmente,
tutta la memoria è a disposizione dei processi utente. Tutta la memoria disponibile viene vista come
un grande buco (hole) e successivamente come una serie di buchi.
Quando si sceglie un processo dalla coda di ingresso, si valuta la memoria disponibile, la quale è
assegnata ai processi della coda fino a che è possibile soddisfare i requisiti del processo successivo,
ossia fino a che esiste un buco di memoria sufficientemente grande da poterlo accogliere.
Normalmente esiste sempre un insieme di buchi liberi di varie dimensioni, per cui, quando si
presenta un processo, il SO cerca un buco al quale assegnarlo; se il buco è troppo grande lo si divide
in due parti, una parte viene assegnata al processo e l’altra viene inserita nella lista dei buchi liberi
disponibili. Quando termina, il processo rilascia il buco, che si reinserisce nel l’insieme di quelli
liberi; se si trova accanto ad altri buchi, si uniscono tutti i buchi adiacenti per formarne uno più
grande. Questo procedimento si chiama allocazione dinamica della memoria.
Le soluzioni all’allocazione dinamica sono diverse, e si basano sui seguenti criteri:
first-fit: si assegna il primo buco di memoria abbastanza grande;
• best-fit: si assegna il più piccolo buco in grado di contenere il processo;
• worst-fit: si assegna il buco più grande.
•
FRAMMENTAZIONE ESTERNA E INTERNA
Entrambi i criteri first-fit e best-fit soffrono di frammentazione esterna, ossia quando si carica e
scarica un processo, la memoria disponibile viene suddivisa in tante piccole parti.
Quindi, si ha la frammentazione esterna quando lo spazio di memoria è abbastanza da accogliere un
processo ma non è contiguo, causando un blocco di memoria libera, sprecato, tra ogni coppia di
processi. La gravità di questo problema dipende dalla dimensione media dei processi; ad esempio,
un’analisi statistica sul first-fit ha dimostrato che, per n blocchi assegnati, se ne perdono in media
0,5n a causa della frammentazione.
La frammentazione può essere anche interna. Questo tipo di frammentazione si verifica quando
l’ultimo buco occupato da un processo rimane parzialmente libero, causando uno spreco di memoria
che però non influisce sulle prestazioni del sistema.
Si può far fronte alla frammentazione esterna mediante la compattazione, il cui scopo è quello di
riordinare il contenuto della memoria per riunire la memoria libera in un unico grosso blocco.
La compattazione è fattibile solo nella fase di esecuzione e solo se la rilocazione è dinamica.
PAGINAZIONE
La paginazione è un metodo di gestione della memoria che permette che lo spazio degli indirizzi
non sia contiguo, risolvendo il problema dell’utilizzo di una memoria ausiliaria.
La sua implementazione si basa sulla suddivisione della memoria fisica in blocchi di memoria
costante, detti frame o pagine fisiche, e sulla suddivisione della memoria logica in blocchi di pari
dimensione, detti pagine. La dimensione delle pagine dipende dall’architettura del calcolatore, ed è
una potenza di 2 compresa tra 512 byte e 16 MB. Quando si deve caricare un processo, si caricano
le sue pagine nei frame disponibili dalla memoria ausiliaria, che è divisa in blocchi di dimensione
fissa, uguale a quella dei frame. L’indirizzo logico generato dalla CPU è
diviso in due campi:
1. numero di pagina p;
2. scostamento di pagina d.
Il valore di p è usato come indice nella
tabella delle pagine, che contiene
l’indirizzo di base in memoria fisica per
ogni pagina. L’indirizzo di base viene
combinato con lo scostamento d per
determinare l’indirizzo fisico.
n
Supponendo che la dimensione di una pagina sia 2 e che la dimensione dello spazio degli indirizzi
m
logici sia 2 , allora i bit dell’indirizzo logico sono così suddivisibili:
n-m bit n bit
Numero di pagina p Scostamento di pagina d
La paginazione non soffre di frammentazione esterna, in quanto qualsiasi frame libero può essere
assegnato, mentre si può verificare quella interna in quanto l’ultimo frame assegnato potrebbe non
essere completamente pieno, dato che la dimensione di un processo generalmente non è multiplo
della dimensione delle pagine.
Quando si deve eseguire un processo si valuta la sua dimensione in termini di pagine. Poiché ogni
pagina deve occupare un frame, se il processo è formato da n pagine sono necessari n i frame; se
questi frame sono liberi essi vengono assegnati. SI carica la prima pagina, e poi la successiva in un
altro frame libero, aggiornando la tabella delle pagine del processo in questione.
La tabella dei frame contiene un elemento per ogni frame, del quale indica se è assegnato o meno,
e se lo è, indica a quale pagina appartiene.
Un altro vantaggio della paginazione riguarda la condivisione di codice comune.
Il codice che si può condividere è quello non automodificante, detto anche codice puro, ossia che
non cambia durante l’esecuzione, e che può quindi essere eseguito da più processi
contemporaneamente.
ARCHITETTURE DI PAGINAZIONE (REGISTRI, PTBR, TLB)
La realizzazione dell’architettura d’ausilio per la tabella delle pagine si può effettuare in vari modi.
Nel caso più semplice si utilizza uno specifico insieme di registri.
La gestione di questi registri dev’essere efficiente, in quanto le istruzioni ad essi relative sono
privilegiate. Per rendere la gestione efficiente, la tabella delle pagine deve avere una dimensione
ragionevolmente piccola (es. 256 elementi), requisito che però non è soddisfatto dai moderni
calcolatori che hanno tabelle delle pagine che raggiungono 1 milione di elementi.
La tabella delle pagine viene mantenuta in memoria e viene puntata da un registro di base della
tabella delle pagine PTBR. I cambiamenti della tabella delle pagine richiedono la sola modifica
del PTBR, riducendo così il tempo dei cambi di contesto.
Tuttavia, si presenta il problema riguardante l’accesso a una locazione di memoria; per accedere a
una locazione con indice i, occorre far riferimento alla page table mediante il contenuto del PTBR
aumentato del valore del numero di pagine di i, accedendo in memoria. A questo punto si ottiene il
numero del frame che, associato all scostamente, fornisce l’indirizzo fisico che permette l’accesso
in memoria. Con questo metodo si effettuano due accessi in memoria.
Per risolvere il problema del PTBR si può utilizzare una piccola cache veloce, chiamata TLB, nella
quale ogni elemento è formato da due campi:
1. una chiave, o tag;
2. un valore.
Le memorie associative sono molto costose e tipicamente contengono pochi elementi.
La TLB si affianca alla tabella delle pagine, infatt