Prima di addentrarci in discorsi prettamente tecnici sarebbe bene
fare un po' di chiarezza sui termini e sui concetti che andremo ad
utilizzare maggiormente all'interno di questo articolo.
Innanzitutto cominciamo col parlare di threads e processi, in quanto spesso
c'è confusione fra i due. Ad un processo il sistema operativo assegna il
suo spazio virtuale di memoria dal quale esso non può uscire fuori. Se un processo deve
comunicare o scambiare dati con un altro processo, esso può farlo solo tramite il
kernel che
rappresenta il core del sistema operativo. I processi sono suddivisi in threads
che possiamo immaginare come compiti che possono essere anche svolti in parallelo. Questi
condividono lo spazio virtuale degli indirizzi di memoria e possono scambiarsi velocemente i dati
senza l'intervento del sistema operativo. I sistemi operativi moderni assegnano un tempo di CPU
mediante una tecnica di priorità proprio ai thread.
Passiamo dunque a definire cosa si intende per "schedulatore"
o scheduler di un sistema operativo. Questa parte dei moderni SO
permette di organizzare la coda dei compiti da svolgere avendo la
consapevolezza di risorse di sistema finite.
In pratica, lo schedulatore assegna un certo tempo di CPU ad una
determinata applicazione affinché essa possa terminare con successo. Uno
schedulatore molto semplice ma anche poco efficace è quello che
serializza le richieste mettendole in coda e non inviando il compito da
svolgere alla CPU prima che sia terminato quello precedente. In questa
situazione, se la CPU è impegnata al 100% nello svolgere un compito
pesante come potrebbe essere quello di una codifica video oppure la
compilazione di un software, l'utente non potrà chiedere altro al
sistema finché il compito precedente non sia terminato. Anche se
l'utente volesse solo muovere il mouse, egli non vedrà la il puntatore
muoversi finché la CPU non sarà nuovamente disponibile.
Appare ovvio che un approccio di questo genere non è proponibile. In
una situazione più realistica il compito dello scheduler è semplice solo
se esso deve gestire una sola applicazione alla volta assegnandole tutto
il tempo di CPU di cui ha bisogno. Per gestire più applicazioni attive
allo stesso tempo, non potendo parallelizzarle a causa delle risorse
hardware, lo scheduler opera secondo uno schema "pre-emptive
multitasking": questa tecnica prevede che un compito possa
prematuramente lasciare libera la CPU per un altro compito che deve
essere eseguito. Nel caso alla CPU siano stati assegnati due compiti
molto pesanti da gestire potrebbe essere che l'utente non noti nulla di
differente fra l'approccio seriale e quello pre-emptive. nel caso in
cui, invece, sia in atto un task molto pesante e l'utente voglia aprire
una applicazione o semplicemente spostare una finestra, egli avrà la
possibilità di farlo e sicuramente crederà che questa azione sia
eseguita parallelamente a quella più pesante.