Il problema più importante dei sistemi multitasking è l'assegnazione delle risorse richieste dai vari processi. Può verificarsi infatti che più processi chiedano contemporaneamente una determinata risorsa unica non condivisibile (es. la stampante): in questo caso se, all’atto in cui un processo ne fa richiesta, essa è utilizzata da un altro processo, l’esecuzione del processo richiedente viene sospesa immediatamente, il processo richiedente viene inserito in una coda d’attesa e solo quando la risorsa verrà rilasciata e nessun altro processo della coda lo precede, potrà acquisire la risorsa e riprendere l’esecuzione.
Un altro problema riguarda l’accesso alle periferiche. Poiché le operazioni di
I/O sui dispositivi sono estremamente lente rispetto alla velocità del
processore, la richiesta da parte di un processo di un operazione di I/O provoca
la sospensione del processo
stesso finché l’operazione non è stata completata ( il meccanismo hardware
messo in gioco è ovviamente l’interrupt )
Da quanto esposto possiamo concludere che un processo può trovarsi in uno di questi tre stati
La gestione dei processi pronti (ready) viene implementata invece che da una coda singola da un set di code ciascuna con una priorità definita. Ad ogni processo viene assegnata una priorità di modo che quando il processo va in stato di pronto viene inserito nella coda con la priorità corrispondente (Round Robin).
Il processo che va in esecuzione è il primo della coda a priorità più elevata. Se in questa non ci sono processi in attesa viene eseguito il primo della coda a priorità di livello inferiore e così via.
Questo meccanismo così come l'abbiamo descritto non è molto efficiente: certi processi di sistema (cioè quelli lanciati dal SO) oppure processi utente
di una certa importanza, possono essere nfatti costretti a lunghe attese (Starvation),
compromettendo il corretto funzionamento del sistema.
Il problema si risolve con la gestione dinamica delle priorità.
All’atto della creazione viene assegnato al processo un determinato
livello di priorità (priorità
statica) . Un criterio comunemente usato per es. è dare ai processi che svolgono prevalentemente operazioni I/O (I/O-Bound) la
priorità più elevata e ai processi che usano prevalentemente la CPU (CPU-Bound)
quella più bassa .
Nel corso dell'esecuzione del processo la priorità può essere cambiata.
Per es. un processo
che entra per la prima volta nel sistema viene inserito nella coda a più alta
priorità. Al primo quanto di tempo, se il processo non ha teminato, viene
inserito nella coda a priorità immediatamente inferiore. (algoritmo di Shortest Elapsed Time)
Il componenete del SO che stabilisce i criteri per l’assegnazione della CPU ai
processi è chiamato Scheduler. Lo scheduler utilizza un modulo chiamato Dispatcher, che svolge tutte le operazioni necessarie per far compiere al processo la
transizione da uno stato ad un altro. La più importante di queste operazioni è
il salvataggio delle informazioni relative al processo rilasciato e il
ripristino di quelle del nuovo processo da mandare in esecuzione (Context
Switching)
Ai fini dell'assegnazione della priorità va tenuto conto di una importante distinzione
fra i processi: processi background e processi foreground.
I processi background non interagiscono con l’utente mentre i processi
foreground generalmente attendono
una qualche forma di input. Tipici processi background sono i daemons (terminologia di
linux/unix): si tratta di processi che vengono mandati in esecuzione
dal SO periodicamente o in seguito al verificarsi di un qualche evento. Ai
processi in foreground viene assegnata una priorità maggiore.
Linux e Windows utilizzano diverse code di priorità corrispondenti ad
altrettanti livelli di priorità. Valori di priorità più bassi indicano
maggiore priorità.
Linux assegna ai processi utente una priorità compresa fra 60 e 100. Per i processi di sistema i valori sono al di sotto di 40. Il superuser può assegnare ad un processo, per es. un comando una priorità il cui valore più basso è 40.
In Windows, ad ogni processo viene assegnata una delle seguenti quattro possibili classi di priorità :
Il PID (process identifier) è un numero di 32 bit che identifica il processo.
L'insieme delle informazioni che individuano un processo prende il nome di descrittore di processo