di allocare (ASSEGNARE) la memoria e partizionarla (DIVIDERLA) tra i vari programmi Processi e memoria
• Tutti i processi in esecuzione necessitano
della memoria centrale per memorizzare: – le istruzioni che fanno parte del codice del programma – i dati su cui operano Gestione della memoria centrale • Il sistema operativo permette l’esecuzione contemporanea di più processi e tutti i processi pronti dovrebbero avere tutto il programma o almeno le prossime istruzioni caricate nella memoria. • Se lo spazio totale occupato dai processi supera la dimensione della memoria centrale, non tutti i processi possono risiedere per intero nella memoria centrale
• Normalmente la quantità di memoria non è
sufficiente a contenere tutti le istruzioni e tutti i dati di tutti i processi gestiti. Gestione della memoria centrale
• La memoria deve essere gestita con molta
attenzione ed efficienza caricando solo i dati e le istruzioni che devono essere modificate ed eseguite. Le altre parti devono essere spostate sul disco rigido per poter essere caricate quando necessario. • La memoria virtuale e’ un sistema per aumentare lo spazio di memoria disponibile Gestione della memoria centrale • Partizionamento della memoria e del suo spazio di indirizzi. • Tecniche di partizionamento: – Segmentazione: suddivide la memoria centrale in segmenti di lunghezza variabili contenenti parti di un programma logicamente correlati tra di loro – Paginazione: suddivide memoria e programmi in pagine di lunghezza fissa; i programmi vengono caricati in memoria anche in pagine non contigue • NON sono tecniche alternative. Spesso sono applicate contemporaneamente. • Sia nel caso della paginazione, sia in quello della segmentazione, il gestore della memoria offre al programma applicativo la visione di una memoria virtuale Indirizzi virtuali • Indirizzi simbolici – nel codice sorgente del programma gli indirizzi sono espressi in modo simbolico • Es. identificatori di variabili nei linguaggi ad alto livello • Indirizzi logici – l'assemblatore (o il compilatore) trasforma gli indirizzi simbolici in valori binari che non rappresentano ancora però un vero indirizzo di memoria. – In genere gli indirizzi logici sono calcolati a partire da un indirizzo iniziale che vale in genere zero (indirizzi binari logici relativi a zero) • Indirizzi virtuali – il linker effettua la traduzione del codice sorgente in linguaggio macchina e genera indirizzi che non sono ancora però riferimenti fisici alla memoria Rilocazione • Indirizzi fisici – Gli indirizzi virtuali possono essere finalmente tradotti in indirizzi di memoria fisica. – Questa operazione di traduzione, in sostanza, costituisce uno dei compiti fondamentali del gestore della memoria. • La traduzione degli indirizzi virtuali in indirizzi fisici è definita rilocazione Rilocazione e protezione • Per evitare che un processo faccia riferimento a zone di memoria appartenenti ad altri processi molti sistemi utilizzano registri speciali di protezione(registri limite) per controllare ed eventualmente inibire riferimenti non autorizzati. • Questi metodi sono ottenibili con sistemi dotati di MMU e i registri base e limite ad esempio possono essere considerati elementi della MMU del sistema. Memory Management Unit (MMU) • E' un componente hardware che gestisce le richieste di accesso alla memoria generate dalla CPU • Una Memory Management Unit (MMU) ha vari compiti, tra cui la traduzione degli indirizzi virtuali in indirizzi fisici, la protezione della memoria, il controllo della cache della CPU ... • La MMU è integrata nei moderni microprocessori Allocazione • Tecnica con cui il SO concede ed assegna memoria ai programmi. • Allocazione statica – processi caricati in memoria che sono allocati una sola volta e sono revocati dalla memoria solo al termine dell'esecuzione • Allocazione dinamica – processi che in esecuzione possono vedersi revocata e riallocata la memoria più volte, in genere con operazioni di swapping *da e per la memoria secondaria. Swapping Swapping è un meccanismo in cui un processo può essere spostato temporaneamente dalla memoria principale ad una memoria di supporto di tipo secondario e poi riportato in memoria per l'esecuzione. Rilocazione statica • La rilocazione statica è quel meccanismo per cui il caricatore (del programma) del SO, dopo aver letto l'intero programma e prima di porlo in esecuzione, rialloca in memoria tutto il codice del programma, adattando gli indirizzi virtuali alle posizioni attualmente disponibili nella memoria fisica. • Il caricatore in questo caso viene detto rilocante; dopo la rilocazione statica il programma in memoria ha assunto riferimenti di memoria fisica che non potranno più cambiare per tutta la durata dell'esecuzione. Rilocazione dinamica • Il SO rialloca il codice durante l'esecuzione del programma, utilizzando elementi di MMU. • A differenza della rilocazione statica la rilocazione dinamica permette ai programmi di essere caricati in aree di memoria differenti durante l'esecuzione; sarà sufficiente modificare le informazioni contenute nel meccanismo hardware che realizza la funzione di rilocazione (meccanismo di MMU). Memoria e multiprocessing • Più processi sono attivi contemporaneamente • Ogni processo necessita di memoria per le istruzioni e i dati • Il Sistema Operativo deve gestire – la protezione dei dati e delle istruzioni relativi a ogni singolo processo – il riutilizzo delle zone di memoria non più utilizzate dai processi Memoria suddivisa in settori • A ogni processo viene assegnato un settore di memoria compreso fra un indirizzo iniziale e uno finale • Il gestore della memoria gestisce una tabella di indirizzi in cui associa ad ogni processo il suo indirizzo iniziale e finale Settori: indirizzi • Indirizzo logico (generato staticamente) – Il compilatore assume che l'indirizzo di partenza per i dati e le istruzioni sia l'indirizzo 0 (zero) • Indirizzo fisico (dove (d si trova realmente in memoria fisica, generato dinamicamente) – In fase di esecuzione gli indirizzi vengono traslati (convertiti) sommando l'indirizzo di partenza del settore associato al processo (operazione effettuata dalla MMU) – Un indirizzo di memoria contiene una parte che identifica un settore (indirizzo logico) e una parte che specifica l'offset *entro il settore. Settori: problemi • Il problema principale è la frammentazione della memoria: – quando termina un processo viene rilasciato il suo settore di memoria che può essere associato a un nuovo processo che richiede una quantità di memoria minore o uguale a quella rilasciata – le parti inutilizzate dei settori portano a una progressiva frammentazione (potrebbe essere disponibile memoria sufficiente per allocare un processo ma non in un settore continuo) Strategie di allocazione • Le strategie di allocazione stabiliscono il criterio scelto per creare o scegliere le partizioni per i programmi che le richiedono. • First fit – Individua la prima partizione atta a contenere il programma e, quindi, tra le partizioni disponibili, viene scelta quella con indirizzi più bassi. Tale tecnica è efficiente per mantenere compattate le zone rilasciate. • Best first – Ricerca nella tabella la partizione più piccola atta a contenere il programma. In questo modo si vengono a creare numerose partizioni libere molto ristrette e quindi si aumenta la frammentazione. • Worst fit – Tra le partizioni libere atte a contenere il programma, sceglie quella più ampia, per attenuare l'effetto della frammentazione. Compattazione • In alcuni casi la riduzione della frammentazione si può ottenere con una tecnica detta di compattazione della memoria. • In questo modo il SO predispone un algoritmo che periodicamente controlla lo stato della memoria e quando necessario interrompe le esecuzioni per compattare in modo contiguo tutta la memoria allocata eliminando i buchi e aggiornando la tabella della memoria. Paginazione • La memoria principale viene «vista» dal processore come un insieme di settori aventi tutti la stessa dimensione predefinita. • Il sistema operativo assegna a ogni processo in esecuzione un numero di pagine sufficiente per contenere il codice e i dati. • Le pagine non sono necessariamente contigue. Tabella delle pagine Organizzazione in pagine Traslazione degli indirizzi
• Per la traslazione degli indirizzi ogni processo è
dotato di una tabella di corrispondenza fra pagina logica e pagina fisica MMU e paginazione • Il compito della MMU è più complesso • Per la traduzione da indirizzo logico a indirizzo fisico: – si individua la pagina logica – poi si individua la corrispondente pagina fisica Dimensione delle pagine • Se la dimensione di una pagina è una potenza di 2 gli indirizzi vengono di fatto spezzati in due: – i primi bit determinano la pagina – i successivi determinano l’indirizzo interno alla pagina (offset) • La traslazione sostituisce i bit relativi alla pagina fisica a quelli relativi alla pagina logica e lascia inalterati i restanti bit • Esempio: indirizzo logico (pagine da 8Kb) – 0001 - 0001 0001 0000 (pagina 1, indirizzo 0x1110) • Indirizzo fisico: – 0100 – 0001 0001 0000 (pagina 4, indirizzo 0x1110) Il compito della MMU Frammentazione • Il problema della frammentazione è risolto • Al termine di un processo vengono “liberate” tutte le pagine utilizzate da questo • Un nuovo processo ha a disposizione tutte le pagine rimaste “libere” Processi in memoria Dimensione della tabella delle pagine • Gli attuali processori indirizzano memorie di grandi dimensioni e la dimensione della tabella delle pagine risulta troppo grande per essere contenuta nella MMU • Per esempio con RAM da 4Gb e pagine da 4Kb (sia Windows che Linux utilizzano pagine da 4Kb) si hanno più di un milione di pagine • La tabella viene quindi memorizzata nella RAM e solo una copia di una piccola parte di questa risiede nella MMU Memoria virtuale • I processi attivi in un sistema operativo multitasking sono molti ed è probabile che il numero complessivo delle pagine richieste da tutti i processi sia superiore al numero di pagine di memoria effettivamente disponibili • Praticamente tutti i moderni sistemi operativi implementano la tecnica della “memoria virtuale”: il gestore della memoria mette a disposizione un numero di pagine superiore a quelle presenti nella memoria fisica • Alcune pagine sono salvate temporaneamente nella memoria di massa (normalmente hard disk) • La memoria di massa utilizzata a questo scopo è comunemente chiamata, in ambiente Unix-Linux, swap o spazio di swap, mentre, in ambiente Windows, è chiamata file di paging. Pagine logiche e fisiche Prestazioni • La memoria di massa ha tempi di accesso estremamente più lenti della memoria centrale: – memoria centrale 50-60 nanosecondi (circa 10 -8 secondi) – memoria di massa 2-4 microsecondi (circa 10 -3 secondi) • E’ necessario quindi ridurre al minimo le operazioni di swapping (spostamento delle pagine dallo spazio di swap alla memoria fisica) Località del codice • Normalmente un processo in ogni fase della sua esecuzione fa riferimento a istruzioni e dati contenuti in poche pagine di memoria contigue. • Località delle istruzioni: l’esempio classico è un ciclo che ripete più volte istruzioni consecutive • Località dei dati: la struttura più comunemente utilizzata è l’array in cui i dati sono contigui in memoria Tabella delle pagine • La MMU trasla gli indirizzi • Se la pagina non è presente in memoria (page-fault) il processo viene posto in stato di wait in attesa che la pagina venga caricata in memoria • Il gestore della memoria recupera la pagina, aggiorna la tabella delle pagine e riporta il processo in ready Page-fault • Ogni page fault rallenta drasticamente l’esecuzione di un processo che deve transitare dallo stato di wait e deve attendere il caricamento della pagina dalla memoria di massa • Se non sono disponibili pagine libere in memoria centrale è necessario sostituire una pagina dello stesso processo (allocazione locale) o di un altro processo (allocazione globale) Politiche per la gestione del page-fault • FIFO (First In First Out) – la pagina da rimuovere è la prima che è stata caricata. L’idea è che le pagine “vecchie” non vengano più utilizzate in futuro • LRU (Least Recently Used) – la pagina da rimuovere è quella inutilizzata da più tempo. L’idea è che se non è utilizzata da molto tempo non verrà più utilizzata • LFU (Least Frequently Used) – la pagina da rimuovere è quella meno utilizzata. L’idea è che se è stata poco utilizzata sarà poco utilizzata anche in futuro Strumenti per la gestione delle politiche • FIFO – è sufficiente memorizzare per ogni pagina il momento del caricamento in memoria • LRU – deve essere memorizzato il tempo ad ogni accesso alla pagina • LFU – deve essere memorizzato un contatore incrementato ad ogni accesso alla pagina – per semplificare la gestione si utilizza un bit che viene settato se di fa accesso a una pagina (i bit vengono periodicamente azzerati) la politica diventa quindi NRU (Not Recently Used) Swapping • Se una pagina viene eliminata dalla memoria centrale deve essere copiata sulla memoria di massa • Un “dirty bit” settato se la pagina viene modificata può essere utilizzato per evitare questa fase di riscrittura su disco (molto spesso per le pagine di codice) Codice condiviso • Molti sistemi operativi prevedono l’uso di funzioni condivise fra vari processi – linux – shared objects – windows – DLL (Dynamic Link Library) • Queste funzioni vengono caricate solo se utilizzate e in questo caso condivise fra i vari processi Windows e Linux