3. Architettura
La progettazione di un SO segue i due principi KISS (Keep It Simple Stupid) e POLA (Principle of Least Privileges), per il quale ogni componente deve avere tutti e solo i privilegi che gli permettono di svolgere la funzione per cui è stato scritto. Si pone inoltre una netta divisione tra policy (caratteristiche che definiscono il sistema) e meccanismi (come queste caratteristiche vengono implementate). Oggi la maggior parte dei SO è suddiviso in componenti, il modo in cui questi interagiscono definisce i vari tipi di architettura.
Sistemi monolitici
I sistemi operativi monolitici sono caratterizzati dalla mancanza di una gerarchia interna: tutti i componenti del sistema sono allo stesso livello e vi è un unico strato software che agisce da interfaccia tra l'utente e l'hardware. Questo significa che tutte le funzionalità del sistema operativo sono disponibili per ogni processo, senza alcuna limitazione gerarchica.
Uno dei principali vantaggi di questo approccio è la sua semplicità: il kernel del sistema operativo è composto da un insieme di procedure che possono chiamarsi reciprocamente, senza la necessità di un'organizzazione gerarchica complessa. Questo rende la progettazione e l'implementazione del sistema operativo relativamente semplice e veloce.
Tuttavia, i sistemi operativi monolitici presentano svantaggi importanti. Uno di questi è che il codice del sistema operativo dipende strettamente dall'architettura dell'hardware su cui è eseguito.
Inoltre, poiché vi è un unico strato software, la fase di test e debug può risultare difficile. Problemi in una singola parte del kernel possono infatti avere effetti negativi su altre parti del sistema, rendendo il processo di ricerca dei bug più complesso e oneroso.
Sistemi a struttura semplice
SO semplice, organizzato con una minima struttura gerarchica, con una strutturazione che mira a ridurre i costi di sviluppo e di manutenzione. La definizione dei livelli della gerarchia è molto flessibile e varia da sistema a sistema.
Un esempio di sistema operativo a struttura semplice è MS-DOS, il quale è stato progettato per fornire il maggior numero di funzionalità possibile nel minor spazio. MS-DOS possiede un minimo di struttura, ma le interfacce e i livelli di funzionalità non sono ben definiti. Inoltre, non prevede la modalità dual (modalità utente e modalità kernel) poiché l'Intel 8088, l'architettura hardware su cui è stato progettato, non lo forniva.
Un altro esempio di sistema a struttura semplice è l'originale versione di UNIX. Questo sistema operativo presenta una struttura base limitata a causa delle limitate funzionalità dell'hardware dell'epoca. La struttura di UNIX consiste in due principali componenti: i programmi di sistema e il kernel, che rappresenta tutto ciò che sta tra il livello dell'interfaccia delle system call e l'hardware. Il kernel di UNIX fornisce funzionalità come il file system, lo scheduling della CPU, la gestione della memoria e altre funzioni.
Struttura a livelli
I componenti sono raggruppati in livelli gerarchici, che vanno dall'interfaccia utente (il livello più alto) all'hardware (il livello più basso). Ogni livello utilizza solo le funzionalità del livello inferiore e fornisce servizi al livello superiore, specificando l'interfaccia.
Tra i vantaggi dei sistemi a livelli, vi è la modularità che facilita lo sviluppo e la manutenzione del sistema. Tuttavia, ci sono anche alcune difficoltà significative, prima fra tutti è la definizione efficace di livelli, dovuta al fatto che le funzionalità dipendenti dall'architettura sono sparse tra i vari livelli e questo diminuisce la portabilità. Inoltre, si ha una minore efficienza a causa di un overhead non trascurabile, dovuto al fatto che eventuali chiamate devono passare attraverso l'intera gerarchia del SO.
Tra gli esempi di sistemi operativi a livelli, si possono citare THE, MULTICS e OS/2. THE, creato da Edsger Dijkstra nel 1968, è considerato il primo esempio di sistema a livelli.
Sistemi basati su kernel
Il sistema è suddiviso in servizi kernel e non kernel, in modo tale che il kernel sia il più piccolo possibile.
Abbiamo praticamente gli stessi vantaggi del sistema a livelli, ma senza averne troppi. Questi SO sono facili da mantenere e da estendere, ma non esiste una chiara definizione per cosa dovrebbe stare nel kernel e cosa no. Kernel complessi e di grandi dimensioni diventano monolitici.
Sistemi basati su micro-kernel
I sistemi operativi basati su micro-kernel cercano di mantenere nel kernel solo ciò che è strettamente necessario. Il file system, l'interprete del sistema e altre funzionalità vengono eseguite in modalità utente, in modo da ridurre la complessità del kernel. Questo approccio presenta alcuni vantaggi rispetto ai sistemi operativi basati su kernel, tra cui una maggiore sicurezza, una maggiore stabilità e una maggiore modularità.
Tuttavia, il principale svantaggio è che le performance sono generalmente peggiori, a causa della necessità di alternarsi continuamente tra la modalità kernel e la modalità utente.
Sistemi a virtual machine
Sono sistemi pensati per poter eseguire sulla stessa macchina più SO contemporanemante, in modo indipendente. Componente chiave è l'hypervisor, il software che crea e gestisce le VM, e che si pone fra l'hardware e il SO, emulando un hardware diverso da quello effettivo. Abbiamo due tipi di hypervisor, di tipo 1 e 2.
- Tipo 1: sopra l'hardware ci sta direttamente l'hypervisor con i vari SO (utilizzato dai Cloud Provider)
- Tipo 2: sopra l'hardware ci sta il SO principale,e sopra, l'hypervisor con il SO secondario. Questo gira come un programma qualsiasi. Questo è il tipo di VM che usiamo per virtual box, è meno performante ma ci permette di usare due SO allo stesso tempo.
Gli hypervisor di tipo 1 si distinguono poichè girano direttamente sull'hardware e sopra di loro i sistemi operativi da eseguire, mentre l'hypervisor di tipo 2 gira come un normale processo su una macchina con un SO (e sopra di esso ancora altri SO).
Uno dei vantaggi principali delle VM è che ogni macchina virtuale è completamente isolata dalle altre, il che significa che se una VM si blocca o presenta problemi, le altre VM continuano a funzionare normalmente senza essere influenzate. Questa isolazione è un grande vantaggio per l'affidabilità e la sicurezza del sistema.
Un altro vantaggio delle VM è che è possibile eseguire più sistemi operativi sulla stessa macchina fisica contemporaneamente.
Inoltre, le VM offrono un'ottima portabilità, in quanto le macchine virtuali possono essere facilmente spostate da una macchina fisica a un'altra, senza dover riprogrammare l'applicazione o il sistema operativo.
Le VM sono anche una scelta popolare per gli sviluppatori di sistemi operativi e software, in quanto consentono di testare le applicazioni in un ambiente sicuro e isolato senza dover acquistare hardware aggiuntivo.
Tuttavia, ci sono anche degli svantaggi nell'utilizzo delle VM. Il primo svantaggio è che ogni macchina virtuale è completamente isolata dalle altre, il che può essere sia un vantaggio sia uno svantaggio, dipende da cosa si vuole fare. Inoltre, poiché ogni VM richiede la propria memoria e le proprie risorse di elaborazione, ci possono essere problemi di performance se troppe VM vengono eseguite contemporaneamente sulla stessa macchina fisica.
Sistemi client-server
Simile al micro-kernel nel modo in cui sposta ai livelli superiori le funzioni non essenziali. Il kernel si occupa della comunicazione tra client e server. Questa architettura è essenzialmente usata nei sistemi distribuiti.
Per quanto riguarda l'implementazione di un sistema operativo, attualmente si utilizzano soprattutto linguaggi ad alto livello come C/C++ per la rapidità di implementazione, portabilità e debugging.
Tuttavia molte direttive, laddove più efficiente, sono scritte in assembler.