# Introduzione ai sistemi operativi
### Aspetti generali

Un sistema operativo è un insieme di programmi che controllano le funzionalità della macchina fisica (il computer) in modo tale da offrire:
* una base ai programmi applicativi
* una prima interfaccia grezza per l'utente.
Senza di esso i programmi applicativi troverebbero serie difficoltà a comunicare con l'hardware del computer. I programmi applicativi accedono quindi alle risorse hardware mediante opportuni componenti del sistema operativo. Va detto che l'interfaccia fornita dal SO non è solo di traduzione del linguaggio della macchina in termini più agevoli, ma consiste anche nella sincronizzazione tra l'applicazione (o anche l'utente) e l'HW.
In modo simmetrico il SO consente di svincolare l'utente (o programma applicativo) dalla macchina.
Il settore dei sistemi operativi ha avuto una continua evoluzione a partire dai primordi dell'informatica, quindi sono svariate le tipologie di sistemi operativi, con tendenza all'arricchimento delle funzionalità fornite al passare del tempo, pur con corsi e ricorsi dove a volte ritornano architetture semplificate, per esempio in macchine con basse potenze di calcolo, che possono essere telefoni cellulari o anche elettrodomestici.
I primi sistemi operativi fornivano solo interfacce testuali (dette anche "a riga di comando"). Oggi i sistemi operativi offrono solitamente un'interfaccia grafica all'utente, in modo da consentire l'uso del computer anche a chi non è un esperto di informatica. I programmi applicativi che scrive lo sviluppatore SW possono usare queste interfacce grafiche, oppure basarsi su interfacce di livello più basso, che consentono di gestire in modo più efficace la macchina.

### Componenti di un sistema operativo

Considerando l'enorme varietà di sistemi operativi sviluppati nel corso del tempo, la definizione esatta dei componenti di esso è variabile, si possono comunque individuare una serie di componenti tipici, la cui denominazione può cambiare in base al produttore:
* il kernel (letteralmente "nocciolo", a volte tradotto con "nucleo") è la parte centrale del SO, solitamente viene eseguito in stato "privilegiato" o "supervisore". In base alle scelte di progetto fatte, può includere o meno i componenti successivi.
   * lo scheduler (quando esiste) si occupa delle politiche di gestione dei processi (o "task", in inglese). Nelle versioni più raffinate e moderne può essere a più livelli e gestire dei "thread" di livello inferiore ai task. Nei sistemi operativi più rudimentali può essere assente, sostituito da un unico processo, che può essere interrotto da interrupt, per passare il controllo alla routine che gestisce l'interrupt.
   * il linker/loader, capace di caricare in memoria un programma eseguibile e mandarlo in esecuzione.
   * i driver di periferica, che interfacciano il SO con le periferiche HW. Qui sono inclusi solitamente i gestori della memoria (di vario genere), le interfacce con tastiera e monitor, l'interfaccia con la stampante, le schede di rete, etc.
* le varie interfacce utente, le quali possono essere di tipo testuale ("shell") oppure grafiche (GUI: graphical user interface).
* uno o più compilatori opzionali per vari linguaggi di programmazione.

### Gestione delle risorse hardware

La gestione dell'hardware viene generalmente organizzata in 5 parti:
* Gestione del processore
* Gestione della memoria principale
* Gestione della memoria secondaria
* Gestione degli altri dispositivi
Un altro aspetto importante è quello della comunicazione e della sincronizzazione dei programmi tra di loro e con l'hardware. Il sistema operativo si occupa di "codificare" tutti i messaggi dei programmi applicativi e prepara le periferiche per l'invio dei dati. Allo stesso modo quando riceve dei dati questi vanno decodificati ed eventualmente inviati ai programmi applicativi che ne faranno uso. Questa funzionalità è importantissima quando si ha un sistema multi-tasking dato che spesso i vari processi devono comunicare tra loro scambiandosi messaggi o segnali di sincronizzazione e il compito del sistema operativo è anche gestire la concorrenza tra i vari processi, ottimizzando anche l'uso delle risorse di elaborazione.

### La supervisione

Il sistema operativo (o più precisamente qualche suo componente, in base all'architettura scelta) è responsabile della supervisione del computer, essendo suo compito l'assegnazione di risorse alle varie entità del computer (utenti, programmi, componenti hardware) in base a politiche prestabilite. Per fare ciò è praticamente sempre necessario distinguere almeno tra uno "stato supervisore", tipico del S.O., ed uno "stato utente" tipicamente assegnato ad un utente del computer. In pratica gli stati saranno solitamente molti di più, ma questi due estremi verranno sempre rintracciati. Quindi i sistemi operativi si distinguono anche dal tipo di supervisione adottata. La supervisione è la parte del sistema operativo che consente o nega un'azione (normalmente sulle periferiche) allo stato utente.

#### Livello servizi (Monolitica)

Lo stato utente permette di accedere senza autorizzazione a poche risorse e nega l'accesso diretto alla memoria principale. La richiesta per accedere ad una qualche risorsa (ad esempio al gestore del processore) viene inviata al nucleo del sistema operativo (anche chiamato kernel) che svolge, tra le altre cose, anche la funzione di supervisore) attraverso una chiamata di sistema (system call). Il kernel decide se e quando mandare in esecuzione il processo in base ad una politica realizzata dall'algoritmo di scheduling (e il modulo che applica l'algoritmo è detto scheduler). In caso di risposta affermativa il kernel mette il processo in esecuzione, altrimenti il processo viene inserito nella coda dei processi pronti.

#### Livello macchina (Server)

Il sistema operativo avvia i processi senza che questi vedano una parte di memoria comune e, per scambiarsi dati e segnali, i processi utilizzano una "rete di comunicazione virtuale". Tale sistema prende il nome di sistema a scambio di messaggi (e la "rete" è detta Inter Process Communication System). Il processo utente per effettuare un'azione invia la richiesta allo specifico server (ad esempio per stampare una pagina invierà la richiesta al server di stampa) attraverso una send asincrona, sincronizzata o con sincronizzazione estesa (Remote Procedure Call) in base al protocollo di comunicazione stabilito fra processo cliente e servitore. Il server, ricevuto il messaggio, riesce a determinare se l'azione richiesta può essere eseguita, dato che conosce lo stato interno della risorsa protetta. Appena possibile esegue l'azione e al termine invia al processo utente l'ok per continuare l'esecuzione e l'eventuale risultato dell'operazione.

#### Quale architettura di SO è la migliore?

* Monolitica:
** Integrato nella maggior parte dei SO (tra cui Unix, Linux e windows)
** Molto veloce
** Molto studiato
** Scarsa protezione
* Server:
** Poco diffuso
** Lento
** Sicurezza elevata
** Ideale per i sistemi operativi di rete.

### Processi e Thread

Come spiegato nella gestione della memoria, ogni processo è indipendente dall'altro, sia come istruzioni sia come memoria. Se, creando un programma, si ha la necessità di eseguire due azioni contemporaneamente, cio è impossibile data la sequenzialità intrinseca nel concetto di processo. Quindi si dovrebbero creare due processi, ma avendo essi la memoria separata, essi dovrebbero continuamente scambiarsi dati, introducendo un grande overhead dovuto all'esecuzione delle system call. Uno schema simile farebbe diminuire drasticamente le prestazioni della macchina e l'esecuzione in contemporanea diventerebbe impossibile ai fini pratici. È qui che vengono in aiuto i thread: dei sottoprocessi chiamati anche "flussi di controllo" o "processi leggeri". I thread hanno svariati vantaggi:
* Costo ridotto (in termini di risorse richieste) per l'attivazione
* Commutazione di contesto molto meno onerosa rispetto ad un processo
* Condivisione della memoria
* Possibilità di utilizzare memoria separata
* Controllo e chiusura di essi relativamente semplice.
Ogni thread possiede un suo stato che può essere: pronto, in esecuzione, bloccato. Un processo, anche se non utilizza thread, ha comunque la funzione principale (in c main) che viene vista come un il singolo thread di un processo. Un esempio molto comune di utilizzo dei thread è un server multi-client. Il server (ad esempio uno di chat) deve interagire con più client (ad esempio se un client invia al server il testo "ciao" il server lo deve inviare a tutti gli altri client). Per fare questo si può attivare un thread per ogni utente connesso che gestisce la comunicazione esclusivamente per quel singolo client. Una volta che il client si disconnette il thread termina.

### Gestione del software

* Gestione dei processi

## I sistemi operativi più diffusi

I sistemi operativi principali e più diffusi (anche in passato) sono (in ordine alfabetico):
* AmigaOS
* BeOS
* DOS
* GNU/Linux
* Mac OS
* OS/2
* OS/390
* OSE
* Solaris
* UNIX
* QNX
* VMS
* Windows