“A microkernel is a small OS core that provides the foundation for modular extension”.
Termine generico per indicare una filosofia di progettazione dei sistemi operativi secondo cui:
Approccio reso popolare dal suo uso nel Mach OS, sviluppato negli anni ‘80 alla Carnegie Mellon University, USA, e che rappresenta oggi il cuore del Mac OS X.
Quali funzionalità devono essere implementate nel microkernel e quali all’esterno?
Un possibile criterio è definire due componenti del SO per la gestione di ogni risorsa:
Ad es., per la gestione dei processi possiamo distinguere:
L’insieme dei meccanismi costituisce di fatto il microkernel, unico componente a girare in modo privilegiato.
Le strategie sono implementate come processi di sistema, ed eseguono come normali applicazioni.
Facilmente modificabili ed estensibili.
I processi di sistema sono spesso indicati come server.
Altri processi (client) accedono ai servizi offerti dai server attraverso i meccanismi di inter-process communication (IPC) del microkernel, basati sullo scambio di messaggi.
Nelle architetture a livelli molti moduli del SO sono parte integrante del kernel.
Le modifiche apportate ad un livello possono avere serie ripercussioni sui livelli adiacenti.
Il malfunzionamento a runtime di una delle funzionalità di un livello può comportare il crash dell’intero sistema operativo.
Interfacce uniformi: tutte le invocazioni di servizio avvengono mediante un’unica interfaccia: lo scambio di messaggi.
Estensibilità: la modifica o aggiunta di funzionalità richiede la modifica o aggiunta di processi applicativi (i server), non del kernel.
Flessibilità: il sistema può essere facilmente adattato a scopi diversi.
Portabilità: la maggior parte del codice dipendente dall’hardware è nel microkernel:
Affidabilità
Supporto all’elaborazione distribuita: il microkernel può astrarre facilmente la rete:
Prestazioni: invocare un servizio attraverso lo scambio di messaggi è generalmente più oneroso di una semplice service call in un sistema modulare.
Una possibile soluzione consiste nel reintegrare nel microkernel servizi o driver critici, invocati spesso
(approccio seguito da Windows e parzialmente da Mach)
… al costo di rendere il microkernel più complesso rinunciando ad alcuni dei suoi vantaggi.
Un microkernel deve fornire almeno i seguenti meccanismi di base:
Questi meccanismi dipendono direttamente dall’hardware e sono la base per il funzionamento di applicazioni e server.
Nel microkernel: funzioni base per il mapping tra memoria logica e memoria fisica e per implementare i meccanismi di protezione a livello di processo.
All’esterno: allocazione, condivisione, gestione dello spazio libero, swapping, ecc.
Esempio: Mach External Pager.
Un possibile set minimo di funzioni per la gestione della memoria offerte dal microkernel:
All’inizio, il kernel alloca tutto lo spazio disponibile ad un processo fittizio di sistema (base system process).
Quando un nuovo processo entra in esecuzione, lo spazio viene ceduto (granted) dal processo fittizio al nuovo processo, e recuperato (flushed) alla sua terminazione.
Il meccanismo di base per la comunicazione tra processi in un microkernel è lo scambio di messaggi.
Il microkernel offre le funzionalità base per inviare e ricevere messaggi.
Un messaggio è composto da un header, che identifica i processi mittente e destinazione, e da un corpo, che contiene i dati da trasferire.
Il microkernel intercetta le interruzioni, ma non le gestisce direttamente…
I driver possono essere implementati come processi esterni che attendono messaggi dalle periferiche e colloquiano attraverso I/O memory mapped.
Driver:
do {
waitFor(msg, sender)
if (sender = my_int) {
read/write I/O;
reset interrupt;
}
else . . . ;
} while (true);
Sviluppato inizialmente come strumento di supporto alla didattica.
E’ basato su un’architettura a micro-kernel:
Il kernel contiene solamente:
Tutti gli altri componenti del sistema operativo sono realizzati come processi eseguiti nello spazio utente!
Minix 3 nasce nel tentativo di rendere un sistema operativo altamente affidabile.
Studi recenti hanno evidenziato che il 70% dei fallimenti di un OS sono dovuti a bachi nei drivers forniti da terze parti.
Minix3 cerca di ridurre l’occorrenza di questi eventi:
In questo modo un driver malfunzionante, non può danneggiare altri che se stesso!
Il kernel schedula i processi e gestisce le transizioni tra gli stati di funzionamento (new, ready, blocked…)
Contiene due moduli: Clock task e System task.
Il Clock task è un particolare driver di I/O che interagisce con l’hardware che genera i segnali di tempificazione.
Non è accessibile dal livello utente, è può essere usato solo dal kernel.
E’ il kernel che notifica ai processi interessati lo scadere di un timer.
Una delle funzioni principali del kernel di Minix3 è quella di fornire un insieme di kernel calls per i drivers nello spazio utente.
Le kernel calls (diverse dalle system calls) permettono ai processi drivers eseguiti nello spazio utente di accedere ad istruzioni privilegiate, come ad es. la lettura e la scrittura su porte di I/O, la copia di dati tra spazi di indirizzamento…ecc.
Queste chiamate sono implementate dal System Task.
System task e Clock task vengono schedulati come due processi distinti, anche se condividono lo stesso spazio di indirizzamento.
La maggior parte del kernel è scritta in linguaggio C.
Tuttavia esiste una piccola parte è scritta in Assembler che gestisce:
I livelli superiori sono visti dal kernel come come un unico livello, abilitato ad eseguire solo istruzioni user-mode, senza poter sforare il proprio spazio di indirizzamento.
Ogni livello ha però dei propri privilegi.
Ad esempio la possibilità di poter effettuare delle kernel-calls è destinate principalmente ai processi drivers.
I drivers sono incapsulati da processi eseguiti in user-mode.
L’unico driver che eseguito in kernel mode è il driver del clock di sistema.
In questo modo ogni driver può accedere solo al proprio spazio di indirizzamento grazie alla MMU.
I drivers accedono all’hardware attraverso le kernel calls.
I drivers comunicano con i processi di livello superiore attraverso primitive per lo scambio di messaggi (overhead rispetto a drivers integrati nel kernel).
L’aggiunta di una nuovo dispositivo non necessita né la ricompilazione né il riavvio del sistema: basta solo avviare il nuovo processo driver!
Ogni driver è organizzato in modo da presentare una parte dipendente dall’hardware e una parte indipendente.
La parte indipendente dall’hardware è in comune ai dispositivi della stessa natura (es. block devices) ed è incapsulata nei server di sistema (ai livelli superiori).
Per tutti i device, ad eccezione del clock, viene richiamato lo stesso interrupt handler chiamato generic_handler che provvede a risvegliare i device driver di competenza il cui valore è contenuto nel campo proc_nr_e della struttura hook
Il caricamento di questa struttura viene effettuato dalla procedura put_irq_handler richiamata, su richiesta dei singoli driver, dal system task
Put_irq_handler inserisce nella ISR table i campi:
I server implementano le system call a livello utente e possono essere invocati tramite scambio di messaggi.
L’invocazione tramite scambio di messaggi è mascherata ai processi utente da comuni chiamate a funzioni, conformi all’interfaccia POSIX.
I server non possono fare operazioni di I/O direttamente, ma devono invocare i driver opportuni.
I server possono anche comunicare con il kernel, attraverso kernel calls servite dal System task.
Il Process Manager (PM) implementa le system call per la gestione dei processi (fork, exec, exit, segnali, ecc.).
Il File System (FS) implementa le system call per la gestione dei file (read, write, mount, chdir, ecc.).
L’Information Server (IS) fornisce informazioni di stato circa i driver e server attivi sul sistema.
Il Reincarnation Server (RS) gestisce il ciclo di vita dei driver ed è progettato per rendere il sistema tollerante ai guasti dei driver.
Round robin su 16 code a priorità differenti.
Quando un processo viene bloccato senza aver esaurito il suo quanto di tempo, una volta risvegliato, viene rimesso in testa alla coda.
Nelle code sono presenti solo processi ready.
Le code da 0 a 4 sono destinate ai system task.
Algoritmo di scheduling:
Darwin è considerato il core di Mac OS X.
E’ costituito da una serie di librerie di utilità e dal kernel XNU.
XNU a sua volta è basato su:
Mach è il core di XNU, ed implementa le seguenti funzionalità base:
XNU contiene una sostanziale quantità di codice derivante da BSD, in parte adattato per permettere l’interazione con il Mach e l’I/O kit.
BSD rende le system call di Mac OS X conformi allo standard POSIX, e quindi compatibili con i SO UNIX, e Linux.
BSD offre i seguenti servizi/funzionalità
I processi BSD sono “mappati” su task Mach.
Il task Mach è l’unità base di allocazione delle risorse.
Ad un task possono essere associati più flussi di esecuzione (thread, di livello kernel).
I thread vivono nel contesto di un task, e rappresentano l’unità fondamentale di schedulazione presa in considerazione dal microkernel.
1. Introduzione ai Sistemi Operativi
5. Scheduling nei sistemi mono-processore
6. Threads, SMP
8. Scheduling Multiprocessore e Real-Time
9. Gestione dei processi nei sistemi operativi Unix/Linux e Window...
10. Introduzione alla Programmazione Concorrente
11. Sincronizzazione nel modello ad ambiente globale
12. Problemi di cooperazione nel modello ad ambiente globale
14. Sincronizzazione nel modello ad ambiente locale
15. Deadlock
16. Programmazione Multithread
18. Memoria Virtuale
20. Il File System
21. Primitive di sincronizzazione nel kernel Linux
22. Esercitazione: System call per la gestione dei processi
23. Esercitazione: Inteprocess Communication e Shared Memory
24. Esercitazione: System Call per la gestione dei semafori in Linu...
25. Esercitazione: Problema dei Produttori e dei Consumatori
26. Posix Threads
Stallings, “Operating Systems” 6th ed., par. 4.3
Tanembaum “Operating Systems” 3rd ed., par. 2.5.1