capitolo 13 - microkernel

Transcript

capitolo 13 - microkernel
CAPITOLO 13 - MICROKERNEL
MICROKERNEL
Questo learning object si occupa del microkernel che è un altro concetto base dei moderni sistemi operativi.
MICROKERNEL
Nella slide sono riportate due
architetture. La prima è riferita ai
primi sistemi operativi dove le
diverse parti del sistema erano
stratificate e si passava di strato in
strato dall’hardware allo spazio
utente attraverso la gestione di
base dei processi, la gestione della
memoria virtuale, la gestione dei
dispositivi di I/O, la comunicazione
interprocesso, la gestione del file
system e poi si giungeva allo spazio
utente. Allo scopo di trasformare i
comandi diretti a sistema, in
altrettanti processi di sistema,
un’interfaccia con lo spazio utente chiamata shell provvedeva a raccogliere i comandi di sistema. Era la struttura del
vecchio OS/360 che comprendeva ben 1.000.000 di linee di codice scritti in cinque anni da 5.000 progettisti, ma anche
quella di Multix che era giunto ad includere ben 20.000.000 di linee di codice.
La seconda architettura è quella a microkernel di un moderno sistema operativo dove vediamo che immediatamente
sull’hardware si trova un microkernel a cui i vari moduli del sistema operativo (chiamiamoli client) si riferiscono in
modalità utente per ottenere servizi da altri moduli (chiamiamoli server) sempre del sistema operativo. Una struttura
verticale è stata sostituita da una struttura orizzontale e tutti i moduli comunicano tra di loro attraverso il microkernel.
In questo modo si realizza un’architettura client/server.
BENEFICI DI UNA ORGANIZZAZIONE MICROKERNEL
- Interfaccia uniforme:servizi del kernel e servizi utente utilizzano tutti gli stessi segnali.
- Estensibilità: estensione di nuovi servizi facilitata (vedasi per es.dischetti con nuove organizzazioni dei file gestite a livello
utente).
- Flessibilità:a secondo delle applicazioni certe caratteristiche possono essere ridotte o potenziate (vedasi la sicurezza).
- Portabilità: Il cambio dell’hardware comporterà unicamente la modifica del microkernel.
- Affidabilità: l’organizzazione modulare permette di realizzare sistemi più affidabili e ai programmatori di conoscere un
minor numero di API.
- Supporto ai sistemi distribuiti: ogni servizio è identificato da un numero nel microkernel e una richiesta da client non è
necessario che sappia dove si trova il server in grado di soddisfare la stessa.
- OOOS: (Object Oriented Operating Sistems).(Parzial. Windows NT)
Prestazioni del MICROKERNEL
Ogni messaggio a microkernel richiede
cambiamento di stato
Utente-kernel
il Questa slide riporta alcune considerazioni sull’uso del microkernel
mettendo in evidenza che poiché ogni chiamata di servizio deve
passare dal microkernel, sarà necessario un cambiamento di
modalità e come sappiamo questo ha un costo in termini di
Siccome tutto passa per il microkernel il gran sovraccarico. Se avvengono molte chiamate di sistema, come
numero di cambiamenti può far decadere il accade naturalmente per il tipo di architettura che stiamo
sistema.
mostrando, può aversi un decadimento del sistema. La soluzione
parziale usata recentemente è di ridurre il numero di chiamate a
Recente soluzione:
sistema che è passato da 140 a 7 chiamate con conseguente
Ridurre il microkernel
ridimensionamento da 300 Kb a 12 Kb del microkernel e con tutti
300 Kb 140 chiamate a sistema
i vantaggi in termini di modularità e quindi d’affidabilità,
12 Kb 7 chiamate a sistema
portabilità, e sicurezza. Alcuni test hanno mostrato che è possibile
si sono ottenute le stesse prestazioni di un sistema ottenere con le strutture a microkernel le stesse prestazioni di un
a strati UNIX
sistema stratificato UNIX.
1
Progettazione del MICROKERNEL
Un insieme minimo di funzioni e servizi del microkernel
per supportare server e applicazioni utente deve
includere:
•
gestione primitiva della memoria
•
comunicazione tra processi (IPC - Inter Protocol
Communication)
•
gestione interrupt ed I/O
La progettazione di un microkernel deve includere un
insieme minimo di funzioni e servizi che devono includere:
- la gestione primitiva della memoria;
- la comunicazione tra processi;
- la gestione dell’interrupt e dell’I/O. Nel seguito vediamo
nei particolari questi tre aspetti.
GESTIONE PRIMITIVA DELLA MEMORIA
In questa slide sono
riportate
le
parti
importanti della gestione
primitiva della memoria.
Il
thread
di
un’applicazione
fa
richiesta di una locazione
di memoria ma non
essendo in memoria
genera un page fault e
l’esecuzione salta al
microkernel.
Il
microkernel chiede al
paginatore di liberare
spazio in memoria principale (Grant), quindi trasferisce la pagina necessaria in memoria principale (Map) e alla fine
rilascia la pagina (Flush). E’ chiaro che la concessione di spazio per allocare una pagina sarà fatta con qualche particolare
algoritmo (LRU).
Comunicazione tra Processi o tra Thread
La base della comunicazione è il messaggio
La base della comunicazione tra processi è il
messaggio. Ogni messaggio include il
Messaggio e (intestazione)+(corpo)+(puntatore a inform.controllo)
processo mittente e il processo ricevente
che costituiscono l’intestazione del
- (intestazione) (include Mittente, Ricevente)
messaggio, i dati da trasferire detto corpo
- (corpo)
(contiene i dati del messaggio)
del messaggio, un puntatore ad un blocco di
- (puntatore)
(a un blocco di dati di controllo del processo PCB)
dati di controllo del processo vedasi (PCB).
La comunicazione avviene attraverso porte
il messaggio è intercettato dal microkernel
a cui vengono accodati i messaggi per quel
•
(capability list)(include i processi da cui si accettano messaggi)
processo. Ogni porta ha associata una
•
Per ogni processo c’è una porta associata attraverso cui arrivano capability list che dice quali sono i processi
i messaggi (il messaggio è messo nella coda dei messagi di quel tipo)
abilitati a comunicare col processo. I
L’accesso alla capability list può essere controllata via microkernel
messaggi sono accodati nelle liste. Ogni
processo può inviare al kernel la nuova
accessibilità.
Gestione dell'Interrupt ed I/O
Il microkernel trasforma l’interrupt in messaggio a livello
utente, pertanto il microkernel riconosce gli interrupt ma
non li gestisce direttamente.
Quando un interrupt abilitato viene accettato, il mKernel
gli assegna il relativo programma mappandolo. I processi
relativi ad interrupt generalmente hanno più alta priorità.
Così ad esempio gli interrupt di I/O si trasformano in
processi di trasferimento.
Ovviamente anche in questo caso è il microkernel che
mappa i programmi relativi alle azioni di I/O.
In un’architettura microkernel è possibile gestire gli
interrupt hardware come messaggi e contenere le porte di
I/O nello spazio di indirizzamento. In altre parole
un’interrupt è riconosciuto dal sistema ma non è gestito
direttamente cioè il microkernel trasforma l’interrupt in
un messaggio a livello utente. Quando un interrupt viene
abilitato il kernel mappa il relativo programma. Quando
l’interrupt si verifica è il kernel che gli associa il relativo
messaggio.
2
Gestione dell'Interrupt ed I/O
Lied ha suggerito di vedere l’hardware come thread con
identificatori unici e mandando messaggi ai thread
associati di livello utente. La slide riporta la routine del
thread del livello utente.
Windows NT - Thread e SMP
Windows NT fornisce supporto ad ambienti di sistema
diversi nei quali i processi differiscono:
-per come sono chiamati;
-per la presenza o meno di thread al loro interno;
-per come sono rappresentati;
-per come sono protette le loro risorse;
-per i meccanismi di comunicazione interprocesso;
-per come sono correlati i processi.
Windows NT fornisce supporto a vari sistemi operativi, da
MS DOS e Posix a Win 32 e a OS2. Alcuni usano solo
processi e altri thread. Ognuno ha un modo diverso di
rappresentare le strutture dati, un suo modo di
proteggere le risorse, i suoi meccanismi di comunicazione
tra processi, un modo diverso di correlare i processi.
Windows NT
I processi di NT sono implementati
come oggetti, ogni processo può
incorporare più thread, thread e
processi hanno la capacità di
sincronizzarsi tra di loro.
Nella slide è mostrata la struttura di
un processo. Quando il processo
viene creato, il suo genitore gli
assegna un token di accesso (token
primario)
che
costituisce
il
meccanismo per la protezione
dell’accesso al processo, infatti nella creazione del token gli viene dato l’identificativo unico che poi passa nel PCB e
insieme anche i diritti. Il processo non ha la possibilità di modificare i diritti d’accesso che sono nel token, gli sono stati
passati e basta, sono stati creati con l’identificazione dell’utente e se li passano di padre in figlio. All’atto della creazione
il gestore della memoria virtuale gli assegna, come si vede in figura, una serie di blocchi. Tra questi c’è quello di un
thread, il primo creato da Windows per quel processo, ovviamente man mano che ne vengono creati altri questi si
accodano alla serie dei blocchi assegnati al processo, c’è un blocco per i file, uno per l’area condivisa. Per accedere ai
blocchi il processo fa uso di una tabella degli oggetti e ai diversi oggetti accede attraverso una maniglia (handle), che
permette di puntare la parte di memoria contenete l’oggetto. Nella figura è anche riportata una handle per la section
z che la sezione di memoria condivisa attraverso la quale i processi e i thread si scambiano messaggi.
3
Descrizione degli Oggetti tipo Processo in Windows NT
Un oggetto processo ha i suoi attributi e i suoi metodi ossia i servizi che
è in grado di svolgere. Nella slide sono riportati gli uni e gli altri. E’
importante notare che nella sezione degli attributi c’è la porta per le
eccezioni attraverso cui passeranno i messaggi, per esempio delle page
fault, quella per la terminazione ecc… Le altre voci della sezione
attributi si commentano da sole, ma è utile richiamare l’attenzione sulla
voce Contatori delle operazioni di MV.
Nella parte sottostante sono invece riportati i servizi. Qui è utile notare
la quantità di servizi per la memoria virtuale, cosa che non troveremo
nei metodi per gli oggetti thread, proprio perché la differenza
sostanziale tra thread e processi è la presenza o meno di risorse.
Descrizione degli Oggetti tipo Thread in Windows NT
In questa slide sono invece riportati gli attributi di un oggetto thread
e i metodi corrispondenti.
Si può osservare che invece del contatore di I/O qui c’è il contatore
di sospensione perché è il kernel che provvederà a fare l’I/O e il
thread si limiterà ad essere sospeso o terminato, c’è anche uno
stato di allerta per quando il thread attende un messaggio.
Alcuni metodi sono analoghi a quelli dei processi ma non ci sono più
tutti i servizi della memoria virtuale invece, ci sono molti servizi
esclusivamente riferiti ai thread.
4
Descrizioni Processo e Thread di Windows NT a confronto
Per dare risalto alle differenze
e sottolineare le differenze tra
processi e thread in questa
slide le due tabelle sono messe
a confronto.
Creazione di un processo in Windows NT
Per LA CREAZIONE DI UN PROCESSO
Windows NT:
1) usa la classe 0-tipo dell’oggetto;
2) vengono assegnati i valori degli
attributi.
Una descrizione dettagliata degli
attributi di un processo è riportata
nella slide. Nella slide è anche
sottolineato che all’atto della
creazione il sistema usa la classe 0
di oggetto e definisce il tipo di
oggetto che in questo caso è un
processo, quindi gli passa i valori
degli attributi.
5
Creazione di un Thread in Windows NT
•
Quando
un
processo viene creato la
prima cosa che fa è di
creare almeno un thread;
•
Nella creazione, il
processo passa al thread
gli attributi di cui a fianco.
In questa slide è invece
messo in evidenza che
come un processo viene
creato
viene
subito
creato un thread e nella
creazione per ereditarietà
molti attributi vengono
passati dal processo al
thread. Nella slide è
anche
riportato
il
significato
dei
vari
attributi dei thread.
Multithreading in Windows NT
•
NT supporta la concorrenza;
•
Il sovraccarico dovuto alla concorrenza può essere eliminato usando
un’architettura multi-processore;
•
Un processo multithread ad oggetti è il modo più efficiente di realizzare
una applicazione server, in questo caso ogni client crea un thread del server.
In questa slide è invece sottolineata
la
particolare
struttura
multithreading di Windows NT con i
maggiori vantaggi che ne derivano.
Stato dei thread in Windows NT
•
Standby
è legato alla disponibilità del
particolare processore richiesto
per il thread.
•
Waiting
da running il T o va da solo in W
oppure se la priorità di un altro T
è più alta il processo in running può
essere interrotto.
•
Transition
si ha quando dopo il waiting si
scopre che le risorse non sono
disponibili (stack swaped).
A partire da questa slide si riportano invece le descrizioni degli stati dei thread rispettivamente in Windows in questa
ed in Solaris nelle successive. In questa sono riportati i sei stati di un thread di Windows NT. In particolare: I tre stati
eseguibili sono Ready, Running e Standby. I primi due non hanno bisogno di commento, nello stato standby un thread
si porta quando non è disponibile il processore di affinità richiesto. Nella parte inferiore della slide ci sono invece altri
tre stati non eseguibili di cui waiting è quello in cui il thread si porta o volontariamente per aspettare che si verifichi un
evento ( wait (semaforo) ) oppure perché è stato forzato da altri (sottosistemi) a portarsi perché accade qualche altra
cosa (I/O). Se quando l’evento è accaduto le risorse sono ancora disponibili allora va in ready altrimenti (vedi uno stack
non più disponibile) va in transition da cui poi andrà a ready. Infine da running il thread va in terminated da cui viene
rimosso o conservato per essere disponibile per altri processi.
6
Supporto ai sottosistemi di Windows NT
E’ responsabilità dei sottosistemi sfruttare le
caratteristiche dei thread e dei processi di NT
per emulare thread e processi dei sistemi
operativi corrispondenti.
Un’applicazione fa richiesta ad un certo
sottosistema di creazione di un nuovo
processo, la richiesta dal sottosistema protetto
va a windows NT. Nel caso di Win 32 ed OS 2,
dovendosi creare un thread la richiesta ritorna
nuovamente a Windows NT per la creazione
del thread. Quindi il processo viene restituito
all’applicazione.
SMP
Windows NT executive dà il supporto ai sottosistemi di ambiente. Quando l’applicazione invia ad un sottosistema la
richiesta di creare un processo, e quindi gli passa il token, questo invia ad executive la richiesta perché sia creato in NT
il corrispondente processo. Se la richiesta è a WIN 32 o OS2, con la creazione del processo, NT crea un thread (attraverso
un meccanismo di richiamata tra sottosistema ed NT), viene definito l’handle di quel thread e passata al sottosistema.
Se invece la richiesta è a Win 16 o POSIX accade che il thread viene creato a livello NT executive ma il sottosistema non
ha conoscenza. Nella creazione del thread è il processo client che trasferisce al thread i valori degli attributi (limite di
quota, priorità di base, affinità di processori) in modo che il thread li eredita dal client e non dal server.
NT supporta anche il SMP. Seguendo il meccanismo delle affinità deboli o forti, NT manda in esecuzione più thread sui
diversi processori della macchina. Nel caso di affinità deboli il thread torna sullo stesso processore su cui era in
esecuzione in precedenza per ritrovare dati già presenti nelle cache, in caso di affinità forti il sistema può restringere
l’insieme dei processori su cui il thread può andare in esecuzione.
Thread e gestione del SMP in SOLARIS
Architettura multithread stratificata
- Thread di livello utente (gestiti dalla libreria Utente)
Processi Leggeri
- Thread di Kernel
L’architettura dei processi e thread in Solaris è stratificata
e passa dai thread a livello utente (gestiti dalla libreria
utente) ai processi leggeri (novità di Solaris), ai thread di
livello kernel. La successiva slide dà una rappresentazione
di questa stratificazione.
Esempio di architettura multithread in SOLARIS
Nella slide sono rappresentati cinque processi P
concorrenti, ognuno con il relativo PCB, uno spazio per il
programma e i dati, e uno spazio per lo stack del kernel.
Essi corrispondono a cinque processi del livello utente.
In alto sono rappresentati i thread di livello utente di
ciascuno dei processi. I thread li crea la libreria, come
avveniva per SVR4. E’nello spazio utente che i thread si
scambiano
messaggi
per
effettuare
la
multiprogrammazione a livello utente.
I vari thread si rapportano a processi leggeri. Ogni
processo leggero è in connessione diretta, in rapporto uno
7
ad uno con un thread kernel. I thread kernel interagiscono poi con il sistema attraverso i processi. A livello kernel è
anche data la possibilità dell’esecuzione parallela dei thread kernel ivi compresa l’esecuzione parallela su processori
differenti SMP. Può essere analizzato uno per uno il grado di parallelismo dei singoli processi riportati nell’esempio
della figura.
Perché Solaris preferisce passare attraverso i processi leggeri piuttosto che andare direttamente ai processi? Perché,
evidentemente, i processi hanno strutture pesanti (si pensi a tutte le strutture dati per la gestione di risorse che devono
comprenderle tutte e per tutti i processi).I processi leggeri, invece, essendo confinati all’interno di un processo non
avranno bisogno delle strutture di tutte le risorse, con conseguente riduzione del carico per il cambio. Tutti i thread
kernel che il sistema crea e distrugge non sono riportati in figura, solo quelli direttamente rapportati al livello utente
sono illustrati.
Struttura dati dei Processi nei vecchi UNIX/e/in SOLARIS
Questa slide descrive la struttura
dati dei processi. A sinistra c’è la
struttura
dati
per
Unix
tradizionale, a destra le
modifiche
introdotte
nelle
strutture dati di Solaris. Come si
vede, la tabella di stato del
processore è sostituita con una
LISTA DI tabelle relative allo stato
dei singoli processi leggeri,
ognuno contiene:
- un identificatore del processo
leggero;
- la priorità con cui viene
eseguito;
- una maschera dei segnali che
vengono accettati;
- i valori salvati dei registri
quando il processo leggero non è
in esecuzione;
- lo stack del kernel;
- l’utilizzo delle risorse e i dati di
monitoraggio;
- il puntatore al thread del
kernel;
- un puntatore alla struttura del
processo.
Esecuzione dei Thread (ULT) (4 azioni che portano al cambiamento di stato)
•
Sincronizzazione (segnali di sincronizzazone T Un thread di livello utente in esecuzione, in Solaris, passa
(Active>Sleeping))
attraverso gli stati di Runnable, Active, Sleeping e Stopped.
•
Sospensione (per azione dello stesso thread T Questi stati sono riportati nella figura successiva a questa.
(Active>Stopped))
In questa slide anticipiamo per facilitare la comprensione
•
Prelazione (un T’ a priorità più alta sospende T quali sono le azioni che portano ad un cambiamento di
Attivo (Active > Runnable))
stato dei thread del livello utente. Sono appunto dovute a
•
Concessione (con thr_yield da T viene creato T’ sincronizzazione, a sospensione, a prelazione,
che diventa active perché va sul processo leggero di T)
concessione.
8
SOLARIS: STATI e DIAGRAMMI
Sincronizzazione / Sospensione/ Prelazione/ Concessione
(thr_yield) /// THREAD ed INTERRUPT
In questa slide è riportato il diagramma delle transizioni
tra stati di un thread di livello utente con il collegamento
al processo leggero a cui è collegato.
Come si è già visto un thread in stato active è associato ad
un processo leggero che corrisponde a sua volta ad un
thread kernel.
A questo thread di livello utente può accadere una delle
azioni già anticipate nella slide precedente e cioè:
-Sincronizzazione: il thread esegue una primitiva di
sincronizzazione e non essendosi verificate date
condizioni deve passare nello stato sleeping.
Quando la condizione si verifica, il thread passa da
sleeping a runnable.
Dallo stato runnable, non appena il processo leggero si
libera, ed il thread viene schedulato, passerà di nuovo
active nello stato di running.
-Sospensione: Il thread essendo attivo, accade che
qualche altro thread o esso stesso lo fermano, allora va in
stopped. Può essere poi rimosso da questo stato per
passare in runnable quando gli viene inviato un messaggio di continuazione.
-Prelazione: un thread fa passare in stato runnable un altro thread a priorità più alta, allora il thread in running viene
interrotto e passa in stato runnable. Quello a più alta priorità diventa attivo e passa in running.
-Concessione: Quando un thread esegue il comando di libreria thr yield viene preso un altro thread di stessa priorità
a cui viene assegnato il processo leggero.
Se la trattazione fin qui fatta ha dato priorità al thread di livello utente, nella parte bassa della figura sono descritte le
transizioni dei processi leggeri.
Se un thread in running ha esaurito il suo slice, passa da running a runnable e quando torna il suo turno ritorna in
running. Se si verifica una azione bloccante passa in blocked e da questo stato con un risveglio passa nuovamente in
runnable, ma può anche accadere che da blocked possa passare in stopped e così via come mostrato in figura.
E’ una chiamata a sistema bloccante che porta il processo leggero nello stato blocked. E’ evidente che la chiamata a
sistema bloccante è altamente probabile che la generi il thread kernel alle spalle del processo leggero.
Si sottolinea, in conclusione, che questa trattazione fa riferimento a processi leggeri multithread di livello utente con
assegnazione di un unico processo leggero ai thread.
Inoltre, è conveniente distinguere per il caso delle transizioni tra stati dei processi leggeri, il caso di thread liberi e il
caso di thread legati al processo leggero.
INTERRUPT COME THREAD
Se la slide precedente ha chiarito l’uso e la
relazione tra ULT e processi leggeri (LWP), la
domanda che viene naturale ora è come sono
organizzati i KLT di Solaris?
Unificando thread kernel e interrupt e
gestendoli con i meccanismi della mutua
esclusione e della sincronizzazione ordinaria
ma provvedendo ad effettuare un
mascheramento e l’assegnazione di livelli di
priorità ai vari thread.
Ad esempio il sistema può inibire interrupt a
tutti i processori di un
sistema multiprocessing!
Se fino ad ora ci si è addentrati nella trattazione dei thread utente e
processi leggeri a questo punto viene naturale la domanda, ma come
sono fatti i thread kernel dell’altro strato sottostante in Solaris?
I processi di sistema e gli interrupt in Solaris vengono visti e gestiti alla
stessa maniera, tutti attraverso thread kernel. Ogni thread ha un
identificativo una priorità un contesto uno stack.
Tutti i thread avanzano concorrente mente, con i normali meccanismi
di sincronizzazione e mutua esclusione che si vedranno nelle lezioni
successive come l’uso di semafori, di primitive di sincronizzazione quali
wait, signal, scambio, test and set e algoritmi vari.
In particolare in Solaris le varie richieste possono essere mascherate
per essere accettare o ignorate, siano esse per interrupt siano esse per
thread kernel.
E’ notevole che la priorità dei thread kernel può essere scalata e i
thread relativi ad interrupt hanno normalmente priorità più alta degli
altri thread.
9