Kernel
In informatica, il kernel è la parte fondamentale di un sistema operativo. Si tratta di un software con il compito di fornire ai programmi in esecuzione sul computer un accesso sicuro e controllato all'hardware. Siccome possono esserci più programmi in esecuzione simultanea, e l'accesso all'hardware è limitato, il kernel ha anche la responsabilità di assegnare una porzione di tempo macchina e di accesso all'hardware a ciascun programma, funzione detta multiplexing. L'accesso diretto all'hardware può essere anche molto complesso, quindi i kernel usualmente implementano uno o più tipi di astrazione dell'hardware. Queste astrazioni servono a "nascondere" la complessità e a fornire un'interfaccia pulita ed uniforme all'hardware sottostante, in modo da semplificare il lavoro degli sviluppatori software.I kernel si possono classificare in quattro categorie:
- Kernel monolitici, che implementano direttamente una completa astrazione dell'hardware sottostante.
- Microkernel, che forniscono un insieme ristretto e semplice di astrazione dell'hardware e usano sofware (chiamati device driver o server) per fornire maggiori funzionalità .
- Kernel ibridi (o microkernel modificati), che sono molto simili ai microkernel puri tranne per il fatto che implementano del codice aggiuntivo a livello di kernel per incrementare le prestazioni.
- Esokernel, che non forniscono astrazione ma che permettono l'uso di librerie per fornire più funzionalità tramite un accesso diretto o quasi all'hardware.
Table of contents |
2 Microkernel 3 Kernel monolitici e microkernel a confronto 4 Kernel ibridi (microkernel modificati) 5 Esokernel |
L'approccio monolitico definice un'interfaccia virtuale di alto livello sull'hardware, con un set di primitive o chiamate di sistema per implementare servizi di sistema operativo come gestione dei processi, multitasking e gestione della memoria, in diversi moduli che girano in modalità supervisore.
Anche se ogni modulo che serve queste operazioni è separato dal resto, l'integrazione del codice è molto stretta e difficile da fare in maniera corretta e, siccome tutti i moduli operano nello stesso spazio, un bug in uno di essi può bloccare l'intero sistema. Tuttavia, quando l'implementazione è completa e sicura, la stretta integrazione interna dei componenti rende un buon kernel monolitico estremamente efficiente.
Il più grosso svantaggio dei kernel monolitici è tuttavia che non è possibile aggiungere un nuovo dispositivo hardware senza aggiungere il relativo modulo al kernel, operazione che richiede la ricompilazione del kernel. In alternativa è possibile compilare un kernel con tutti i moduli di supporto all'hardware, ingigantendo però le sue dimensioni. Tuttavia i kernel monolitici più moderni come il Kernel Linux e FreeBSD possono caricare dei moduli in fase di esecuzione, a patto che questi fossero previsti in fase di compilazione, permettendo così l'estensione del kernel quando richiesto, mantenendo al contempo le dimensioni del codice nello spazio del kernel al minimo indispensabile.
Esempi di kernel monolitici:
L'approccio microkernel consiste nel definire della macchine virtuali molto semplici sopra l'hardware, con un set di primitive o chiamate di sistema per implementare servizi minimali del sistema operativo quali gestione dei thread, spazi di indirizzamento o comunicazione interprocesso.
L'obiettivo principale è la separazione delle implementazioni dei servizi di base dalle strutture operative del sistema. Per esempio, il processo di blocco (locking) dell'Input/Output può essere implementato come modulo server a livello utente. Questi moduli a livello utente, usati per fornire servizi di alto livello al sistema, sono modulari e semplificano la struttura e la progettazione del kernel. Un servizio server che smette di funzionare non provoca il blocco dell'intero sistema, e può essere riavviato indipendentemente dal resto.
Esempi di microkernel:
I kernel monolitici sono spesso preferiti ai microkernel a causa del minor livello di complessità nel controllo dei codici di controllo in uno spazio di indirizzamento. Per esempio XNU, il kernel di MacOS X, è basato su un kernel Mach 3.0 più BSD nello stesso spazio di indirizzamento in modo da abbattere i tempi di latenza tipici dei microkernel.
A partire dai primi anni '90 i kernel monolitici sono considerati obsoleti. Il progetto di Linux come kernel monolitico anziché come microkernel è stato uno degli argomenti della famosa guerra di religione fra Linus Torvalds (il creatore di Linux) e Andrew Tanenbaum (celebre docente di sistemi operativi, autore di Minix e padre del linguaggio Pascal) - in rete sono disponibili maggiori dettagli.
In realtà vi sono ragioni da entrambe le parti.
I kernel monolitici tendono ad essere più semplici da progettare correttamente, e possono quindi evolversi più rapidamente di un sistema basato su microkernel. Ci sono storie di successi in entrambi gli schieramenti. I microkernel sono spesso usati in sistemi embedded in applicazioni mission critical di automazione robotica o di medicina, a causa del fatto che i componenti del sistema risiedono in aree di memoria separate, private e protette. Ciò non è possibile con i kernel monolitici, nemmeno con i moderni moduli caricabili.
A parte il kernel Mach, che è il più noto microkernel di uso generico, molti altri microkernel sono stati sviluppati con scopi specifici. L3 in particolare è stato creato per dimostrare che i microkernel non sono necessariamente lenti. La famiglia di microkernel L4, successori di L3, dispongono di una implementazione chiamata Fiasco in grado di eseguire il Kernel Linux accanto agli altri processi di L4 in spazi di indirizzamento separati.
QNX è un sistema operativo presente sulle scene dai primi anni '80 e dispone di una implementazione a microkernel davvero minimalista. Questo sistema ha avuto molto più successo di Mach nel raggiungere gli obiettivi del paradigma a microkernel. È usato in situazioni in cui al software non è concesso di sbagliare, ad esempio nei bracci robotici dello space shuttle o in macchine che lavorano il vetro dove un errore anche piccolo può costare centinaia di migliaia di Euro.
In molti credono che, siccome Mach ha fallito nel compito di risolvere tutti i problemi per i quali i microkernel erano stati concepiti, l'intera tecnologia microkernel sia fallimentare ed inutile. Invece i sostenitori dei microkernel sostengono che questa sia una concezione poco aperta mentalmente e che sia diventata così popolare da essere ormai accettata come verità .
I kernel ibridi sono essenzialmente dei microkernel che hanno del codice "non essenziale" al livello di spazio del kernel in modo che questo codice possa girare più rapidamente che se fosse implementato ad alto livello. Questo fu un compromesso adottato da molti sviluppatori di sistemi operativi prima che fosse dimostrato che i microkernel puri potevano invece avere performance elevate. Molti sistemi operativi moderni rientrano in questa categoria: Microsoft Windows è l'esempio più noto. Anche XNU, il kernel di Mac OS X, è di fatto un microkernel modificato, per via dell'inclusione di codice BSD in un kernel basato su Mach. DragonFly BSD è stato il primo sistema BSD non basato su Mach ad adottare l'architettura a kernel ibrido.
Alcune persone confondo il termine "kernel ibrido" con i kernel monolitici che possono caricare dei moduli dopo il boot. Questo non è corretto, poiché "ibrido" implica che il kernel in questione condivida concetti architetturali e meccanismi tipici sia dei kernel monolitici che dei microkernel, specialmente il passaggio di messaggi e la migrazione di porzioni di codice "non essenziale" a più alto livello, mantendendo a livello kernel solo il codice necessario per ragioni di prestazioni.
Esempi di kernel ibridi:
L'idea che sta dietro è che nessuno sa come rendere efficiente l'uso dell'hardware disponibile meglio di uno sviluppatore, quindi l'obiettivo è dargli la possibilità di prendere le decisioni. Gli esokernel sono estremamente piccoli e compatti, in quanto le loro funzionalità sono arbitrariamente limitate alla protezione e al multiplexing delle risorse.
I kernel "classici" (sia monolitici che microkernel) astraggono l'hardware, nascondendo le risorse dietro a un livello di astrazione dell'hardware (hardware abstraction layer o HAL), o dietro a server "sicuri". In questi sistemi "classici" ad esempio, se viene allocata della memoria il programma non può sapere in quale pagina fisica questa verrà riservata dal sistema operativo, e se viene scritto un file non c'è modo di sapere direttamente in quale settore del disco è stato allocato. È questo il livello di astrazione che un esokernel cerca di evitare. Esso permette ad un'applicazione di richiedere aree specifiche di memoria, settori specifici su disco e così via, e si assicura solamente che le risorse richieste siano disponibili e che le applicazioni vi possano accedere.
Quindi, siccome un esokernel fornisce un'interfaccia davvero a basso livello all'hardware, mancando di qualsiasi funzionalità di alto livello tipica degli altri sistemi operativi, esso è accompagnato da un "sistema operativo-liberia".
Questo "libOS" si interfaccia all'esokernel sottostante e fornisce agli sviluppatori di applicazioni le funzionalità di un sistema operativo completo.
Tutto ciò ha un'importante implicazione: è possibile avere diversi libOS sul sistema. Se, per esempio, si installa un libOS che esporta un'API Unix e uno che esporta un'API Windows, è possibile eseguire simultaneamente applicazioni compilate per UNIX e per Windows. Lo sviluppo dei libOS avviene a livello utente, senza reboots, debug su console e in piena protezione della memoria.
Al momento gli esokernel sono più che altro dei progetti di ricerca e non sono usati in sistemi operativi commerciali. Un esempio di sistema basato su esokernel è Nemesis, sviluppato dall'Università di Cambridge, dall'Università di Glasgow, da Citrix Systems e dall'Istituto Svedese di Informatica. Anche il MIT ha sviluppato diversi sistemi basati su esokernel.
Kernel monolitici
Microkernel
Kernel monolitici e microkernel a confronto
Kernel ibridi (microkernel modificati)
Esokernel
Gli esokernel, conosciuti anche come "sistemi operativi verticali", sono un approccio radicalmente differente alla progettazione dei sistemi operativi. L'idea centrale è "separare la protezione dalla gestione".