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.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
Gestione degli interrupt e virtualizzazione delle CPU
N.B. È la gestione degli interrupt che avviene nel kernel che permette la virtualizzazione delle CPU. Per la virtualizzazione del processore bisogna gestire gli interrupt a livello kernel, questa parte dell'interrupt è una parte del SO che interagisce con l'esterno o con interrupt di tipo software o con interrupt di tipo hardware e quindi I/O, senza questi interrupt non si può virtualizzare la CPU.
Al fine di gestire le risorse un processo non può accedere direttamente alla risorsa ma deve fare una richiesta al SO e queste richieste prendono il nome di system call e rappresentano un altro input per il SO. Abbiamo allora due handler, uno per le System Call e l'altro per gli Interrupt SW e HW.
Tra gli output del SO abbiamo lo Switch tra i vari processi. All'interno del SO sono presenti delle strutture dati che prendono il nome di code, la gestione delle strutture dati più importanti sono le code.
Il kernel del SO si può...
definire in soldoni come una serie di ISR o handler. Un SO è guidato dagli interrupt che possono generalmente essere di tipo sincrono o asincrono. Gli interrupt di tipo asincrono sono tipicamente quelli dell'hardware mentre quelli sincroni sono sincroni all'esecuzione del programma ed è quindi un processo che ad un certo punto invoca l'esecuzione di un interrupt. Un Processo esegue le istruzioni fino a quando non trova un'istruzione che richiede l'accesso ad una risorsa, per accedere al disco bisogna accedere ad un registro di controllo proprio del disco ed il processore deve in qualche modo eseguire delle istruzioni sensibili per accedere a questo registro. L'implementazione della open si trova allora nel kernel in quanto se tutte le open fossero a livello utente non ci sarebbe protezione e tutte le open potrebbero accedere al registro di controllo. Un processore, almeno quello generale, si può trovare in due stati: 1) ModalitàUtente -> un processore può eseguire tutte quelle istruzioni non sensibili
Modalità Supervisore -> una CPU può eseguire tutte le tipologie di istruzioni anche quelle sensibili come ad esempio quelle di controllo, quelle di reset dei flag, quelle di reset delle interruzioni ecc.
Per passare dalla modalità utente a quella di supervisore esiste un'interruzione che prende il nome di TRAP che va ad attivare un bit nello Status Service.
Quando viene chiamata una open ad esempio, avendo delle istruzioni sensibili che richiedono di andare a resettare dei flag, ad attivare delle interruzioni e quindi contiene un'istruzione che scatena un'interruzione, una TRAP che scatena il passaggio dalla modalità utente alla modalità supervisore e quindi permette di eseguire il codice della open a favore del processo permettendole di accedere al disco, una volta terminata l'esecuzione restituirà il controllo al processo.
Quanto detto
accade perché i processi vengono ad essere eseguiti in modalità utente e non supervisore e questo rende necessario il SO. Una System Call è quindi una chiamata di sistema ed è l’unico modo che ha un processo per richiedere l’accesso ad una risorsa al SO. Poiché tutte le risorse sono controllate dal kernel del SO, l’unico codice che può essere eseguito in modalità supervisore (kernel mode) è il codice del kernel; la System Call si presenta quindi al processo come se fosse una funzione di libreria ma al suo interno innesca una chiamata ad una TRAP che è un’interruzione che consente il passaggio dalla modalità utente alla modalità supervisore, ad un certo punto entra in gioco il SO che capisce tramite un passaggio di parametri qual è la system call che deve essere eseguita e fa una call ad una routine del kernel per eseguire la system call ed in questo modo viene ad essere eseguito ilCodice della system call per conto del processo, una volta eseguita vi è il ritorno dalla TRAPe si ritorna dalla modalità supervisore alla modalità utente. 32
Le System Call si possono dividere in 5 macro categorie che sono elencate sotto. Le System Call di comunicazione sono tutte quelle chiamate di sistema che il SO mette a disposizione per la comunicazione dei processi e che prendono il nome di IPC (Inter Process Communication). 33
La system call deve per forza sottintendere un passaggio da user mode a kernel mode e questo può avvenire solo sottintendendo una trap, viene ad essere quindi invocata una routine del kernel che esegue quel codice a favore del processo e quindi espleta il servizio richiesto che una volta espletato porta il passaggio inverso e quindi da kernel mode ad user mode. Nei SO per evitare l'overhead introdotto dalle trap il passaggio da kernel mode a user mode può essere invocato mediante un'istruzione speciale, quindi nelle
architetture moderne è possibile andare a bypassare queste trap.
N.B Sono i processi che vengono schedulati non le system call che sono funzioni all'interno del kernel.
Quando accendiamo il PC in una ROM esiste un programma che prende il nome di boot program che controlla la configurazione hardware del PC, questo programma di boot si costruisce un record con tutta la tipologia di hardware del nostro sistema e poi attraverso un piccolo caricatore che sa dove andare a leggere per caricare il SO, comincia a caricare il SO, tale parte è costituita da quei file ibm o ibmdos di windows che costituiscono i veri e propri caricatori che cominciano a caricare il kernel del SO.
Questo piccolo caricatore ha quindi il compito, una volta caricata la struttura dati che gli viene fornita, di andare ad evocare il caricatore del SO che permette il caricamento del SO e da avvio a quella che è la vera e propria fase di inizializzazione.
Il SO parte o a seguito di interruzioni, o
La figura sopra evidenzia quali sono gli eventi che scatenano il SO ed evidenzia bene che l'unico codice che può essere eseguito in modalità supervisore (modalità kernel) è proprio il kernel.
Gli interrupt provengono dal mondo hardware e questo accade perché un dispositivo hardware comunica attraverso una linea di interruzione che il risultato è pronto e sulla linea di interruzione ad una certa posizione si trova un vettore delle interruzioni attraverso il quale si localizza il dispositivo che ha causato l'interrupt e si identifica qual è la ISR da eseguire e poi si va a vedere quale processo era sospeso in attesa dell'I/O e lo si va a riattivare sulla CPU. Gli interrupt sono trasparenti alle applicazioni e servono al SO per alternare i processi sulla CPU.
Le eccezioni per loro natura devono per forza essere non formattate.
trasparenti perché sono operazioni anomale, non legali eseguite dal programma utente e quindi il SO deve intercettare e molte volte deve prendere un provvedimento come uccidere il processo (Kill del processo). 38 Anche la System Call è trasparente all'esecuzione del processo. Il SO è costituito da funzioni piccole che fanno poche cose e quindi è facile leggerne il codice che lo costituisce. 39 I primi kernel erano monolitici e quindi erano un unico file binario compilato, non ci sono suddivisioni, non ci sono moduli fisicamente divisi. Tutte le ISR, tutte le procedure sono in un unico file binario, vi era un unico spazio di indirizzamento, un unico file binario che veniva caricato al boot nelle macchine. Il vantaggio di questa tipologia di architettura è che è presente un unico spazio di indirizzamento e quindi le prestazioni sono molto elevate in quanto vi è un unico programma che gira e le chiamate sono all'interno dello stesso.
spazio di indirizzamento e quindi risultano essere molto più performanti di quelle che si hanno in moduli che appartengono ad un diverso spazio di indirizzamento.
Gli svantaggi di questa architettura è che dovevano essere linkati staticamente all'interno del kernel tutti i driver delle periferiche hardware. Quindi un primo svantaggio era costituito dall'estensibilità del SO che per essere cambiato necessitava di essere modificato e ricompilato, un altro svantaggio era dato dal fatto che qualora ci fosse un errore in una qualunque istruzione del kernel questo avrebbe causato il crash dell'intero SO dovuto ad un kernel panic.
Nelle architetture monolitiche modulari abbiamo che il kernel è sempre costituito da un unico nucleo ma in questo nucleo esistono diversi moduli che possono essere caricati a run time. Ancora oggi il kernel Linux è costituito da un kernel monolitico unico, con un unico spazio di indirizzamento a cui però sono
linkati dinamicamente nuovi moduli per aggiungere nuovi driver o nuove funzionalità. L'architettura modulare, come possiamo vedere dalla figura sopra, funziona con un kernel monolitico e con la possibilità di aggiungere nuovi moduli. Il kernel è quindi fatto a moduli separati che possono essere linkati tra di loro, sia dinamicamente che staticamente. Si ha quindi la massima flessibilità, l'importante è che il kernel venga ad essere confinato all'interno di un unico spazio di indirizzamento. Lo svantaggio di questa tipologia di sistemi è rappresentato dall'affidabilità, in quanto gli errori sui driver o su un altro modulo possono provocare il crash dell'intero sistema. Ancora oggi abbiamo questa tipologia di problemi, infatti quando installiamo un sistema Linux, se prendiamo la versione Debian stable, abbiamo che andiamo ad installare una versione del software già vecchia, in quanto abbiamo tutti i driver che andiamo adinstallare sono dei driver testati, questo perché le architetture monolitiche hanno problemi di robustezza dovuti a problemi nel codice. Microsoft non ha potuto seguire le orme di Linux in quanto ha moltissime configurazioni hardware a differenza ad esempio di MAC che ha una configurazione limitata di hardware disponibili. La differenza quindi sta nel fatto che MAC ha la possibilità di scriversi i driver da sé e testarli e può quindi usare una tipologia di kernel monolitico mentre Windows vista l'enormità di hardware che si deve trovare a gestire ha le necessità di dover utilizzare driver provenienti anche da terze parti. La figura sotto fa capire bene quali sono i livelli logici di una macchina e quali sono le diverse sorgenti e come vengono ad essere gestite. Questa figura ci fa capire come la pulizia del kernel di Linux oggi sia unica e di come questa sia strutturata a livelli.