Il OS è coinvolto con la paginazione in quattro momenti :

  • creazione del processo
  • esecuzione del processo
  • durante un page-fault
  • terminazione del processo

Creazione del processo

Quando viene creato un processo, il OS deve eseguire una serie di operazioni :

  1. determinare il numero di pagine da assegnare al codice e ai dati e poi creare le corrispondenti tabelle delle pagine
  2. allocare e inizializzare la tabella delle pagine
  3. riservare lo spazio di swap (spazio su disco), per garantire lo swap (scambio) delle pagine
  4. inizializzare l’area di swap su disco con il codice e i dati in modo che quando il processo viene avviato, il primi page fault caricano le pagine necessarie in memoria (tecnica di demand paging)
  5. registrazione nella tabella dei processi delle informazioni relative alla tabella delle pagine e l’area di swap su disco

Esecuzione del processo

Quando un processo viene schedulato per l’esecuzione, tutta la parte di gestione della memoria deve essere rapidamente aggiornata per gestire il nuovo spazio di indirizzamento virtuale del processo che deve essere eseguito :

  • ripristino della MMU
  • svuotamento della TLB (se necessario)
  • caricamento della tabella della pagine del processo, quindi deve diventare la tabella corrente
  • pre-paginazione : caricare alcune pagine in memoria per ridurre i primi page fault (facoltativo)

Gestione page fault

Quando accade un page fault accadono i seguenti eventi :

  1. trap kernel : hardware esegue una trap del kernel e il program counter viene salvato nello stack
  2. routine assembly : avviata una routine assembly
    • per salvare i registri di stato e altre informazioni volatili del processo corrente
    • invocazione gestore dei page fault
  3. identificazione page : OS cerca di scoprire la pagina virtuale manca
  4. verifica indirizzo : una volta conosciuto l’indirizzo virtuale, il OS verifica che sia valido e la protezione sia coerente con l’accesso richiesto (se invalido invia un segnale di errore o termina il processo)
  5. rilascio frame : se c’è un frame libero ok, altrimenti attiva l’algoritmo di sostituzione delle pagine che individua una pagina “vittima” da sostituire
    • se la pagina selezionata come “vittima” è “sporca”, viene schedulato il trasferimento su disco e sospeso il gestore di page fault finché il trasferimento non è finito
  6. caricamento page : una volta che il frame è stato scritto su disco, il OS schedula un’operazione per portare in memoria la pagina mancante nel frame appena liberato
    • il processo in page fault è in sospeso, e quindi può essere schedulato un altro processo utente
  7. update table : una volta che l’interrupt del disco arriva, indica che la pagina è arrivata e le tabelle delle pagine vengono aggiornate per riflettere la nuova posizione della pagina
  8. ripristino istruzione : l’istruzione che ha provocato il page fault viene ripristinata
  9. ritorno routine : il OS ritorna alla routine in assembly che lo ha chiamato
  10. ricarico registri e ritorno user space : questa routine ricarica i registri e le altre informazioni di stato, quindi si ritorna allo spazio utente per proseguire l’esecuzione

Terminazione del processo

Quando un processo termina, il OS deve eseguire una pulizia delle risorse di memoria associate a quel processo :

  • rilasciare la tabella della pagine, le pagine e lo spazio su disco/SSD
  • gestisce le pagine condivise, in modo che altri processi che stanno utilizzando una pagina condivisa non abbiano problemi

Blocco delle pagine

L’interazione tra memoria virtuale e I/O è un aspetto delicato nella progettazione del OS.

Supponiamo per esempio :

  1. P1 lettura I/O → DMA scrive nel buffer di P1 (indirizzo fisico X)
  2. P1 viene sospeso
  3. P2 va in esecuzione e ha un page fault
  4. Con allocazione GLOBALE → il OS può scegliere come vittima la pagina del buffer di P1
  5. DMA continua a scrivere su X → corruzione

Esistono allora 2 soluzioni :

  • pinning delle pagine : bloccare (“fissare” - pinning) le pagine in memoria che stanno effettuando operazioni I/O, in modo che non vengano rimosse
  • buffer nel kernel : eseguire tutte le operazioni I/O all’interno dei buffer del kernel e poi copiare i dati su pagine utente (copia aggiuntiva rallenta)

Swapping delle pagine su disco

Quando una pagina viene rimossa dalla memoria è fondamentale stabilire dove e come la pagina viene conservata sul disco.

Una tecnica semplice è di usare una partizione dedicata (di swap) o ancora meglio su un disco separato (con file system semplificato). (es. UNIX)

Quando il sistema viene avviato, la partizione di swap è inizialmente vuota ed è grande quanto il processo. Quindi la partizione di swap può essere gestita come una lista di “pezzi” (chunks) liberi.

Ad ogni processo è associato l’indirizzo del disco della sua area di swap.

Quindi calcolare l’indirizzo dove scrivere una pagina diventa semplice, infatti basta sommare l’offset della pagina all’indirizzo di inizio della sua area di swap.

Strategie di paginazione e ottimizzazione

Il problema è che i processi possono crescere dopo l'avvio, risulta quindi migliore riservare aree di swap separate per il testo, dati e lo stack. Nello swapping statico ad ogni processo viene assegnato sul disco uno spazio identico a quello occupato in memoria.

Un’alternativa sarebbe l’allocazione dinamica, ovvero di non allocare niente all’inizio, ma di allocare spazio su disco nel momento di swap di ogni pagina. Lo svantaggio è che c’è bisogno di tenere traccia di ogni indirizzo del disco per ogni pagina, ovvero è necessaria una ulteriore tabella che ci dica per ogni pagina dove si trova nel disco.


Avere una partizione di swap fissa non è sempre possibile, per esempio se non ci sono partizioni del disco disponibili. In questo caso, uno o più file pre-allocati può essere utilizzato all’interno del file system normale (utilizzato da Windows).


Segmentazione