Il SO è caratterizzato dalle politiche adottate per decidere quali task eseguire e per quanto tempo devono essere eseguite (politiche di scheduling). Il componente del SO che realizza le politiche di scheduling è detto scheduler.
Lo scheduler dovrebbe garantire che i task più importanti vengano eseguiti prima di quelli meno importante, che i task di pari importanza vengano eseguiti in maniera equa, e in particolare, che nessun task debba attendere un turno di esecuzione per molto più tempo degli altri task.
ou
Lo scheduler è un componente critico nel funzionamento di un sistema operativo ed è oggetto di molta ricerca per migliorarne le caratteristiche e le prestazioni.
Per un sistema multi-programmato, la gestione dell'esecuzione dei task più immediata, semplice e ragionevolmente equa è la politica del round robin. Dati
Lo scheduler interviene in certi momenti per determinare quale task rimettere in esecuzione, e contestualmente toglie un task dall'esecuzione. La scelta del task da rimettere in esecuzione avviene tra tutti i task in stato di pronto esistenti nel sistema, cioè tra tutti quelli nella runqueue. Il task scelto è quello che in quel momento ha il diritto di esecuzione maggiore.
Ci sono tre casi in cui lo scheduler deve scegliere un task corrente:
I task possono avere requisisti di scheduling molto diversificati per applicazioni. Suddividiamo quindi i task in tre categorie:
Per gestire ciascuna categoria di task secondo le rispettive caratteristiche distintive, lo scheduler realizza varie politiche di scheduling. Ogni politica è realizzata da una classe di scheduling diversa (contenuta nel descrittore del task).
Lo scheduler è quindi l'unico gestore dei task in stato di pronto, cioè della runqueue. Per questo motivo tutte le altre funzioni del SO e in particolare quelle del nucleo devono chiedere allo scheduler di eseguire operazioni sulla runqueue.
Attualmente le tre classi di scheduling più importanti del SO Linux sono SCHED_FIFO, SCHED_RR, SCHED_NORMALE.
Dove i task ti classe FIFO hanno sempre precedenza su tutti quelli delle altre due classi, i task di classe RR hanno sempre precedenza su tutti quelli della classe NORMAL, e i task di classe NORMAL danno sempre precedenza a tutti quelli delle altre due classi.
Le classi SCHED_FIFO e SCHED_RR sono usate per i task di tipo soft real-time. Il SO linux non supporta i processi RT in senso stretto.
A ciascun task di queste due classi viene attribuita alla creazione una priorità detta statica, perché è assegnata all'inizio e poi non varia più.
Solitamente un task figlio eredità la priorità statica del task padre, e si può cambiare la priorità statica di un task utilizzando comandi di amministrazione.
La priorità statica del task è memorizzata in task_struct
nel campo static_prio
.
Lo scheduler Linux candida all'esecuzione i task di classe NORMAL seol se in stato di pronto non ci sono task delle classi FIFO e RR, che li precedono sempre. Lo scheduler di Linux per i task di classe di scheduling SCHED_NORMAL è chiamato Completely Fair Scheduler (CFS).
CFS ambisce a raggiungere questo obiettivo: dati
Se il sistema è multiprocessore ciascuna CPU ha una sua runqueue da gestire modo CFS.
Per raggiungere il suo obiettivo lo scheduler CFS deve:
Ad ogni task si assegna un peso iniziale, che quantifica l'importanza del task. La costante di sistema L0
definisce il peso iniziale. Per ipotesi assumiamo che il peso per tutti i task t presenti nella runqueue sia L0
, e che nessun task si autosospenda.
Si ha che il numero di task nella runqueue a un certo istante è
I task vengono mantenuti nella coda ordinata RB, e il funzionamento dello scheduler CFS è schematizzabile nel modo seguente:
Il periodo
Il periodo di scheduling
Il meccanismo base si basa su un quanto
L'aspetto più importante di CFS è quello relativo alla misura virtuale del tempo, che ricalcola certe variabili per ogni task ad ogni impulso del real-time clock, ad ogni risveglio del task e ad ogni creazione di un task. La decisione su quale task mettere in esecuzione viene poi presa dalla funzione schedule
quando viene chiamata.
Si valuta il peso relativo di ogni task load_coff
come:
Possiamo quindi stabilire la durata del quanto di tempo come:
Lo scheduler CFS utilizza Virtual RunTime (VRT) per ordinare i task nella runqueue. VRT è una misura virtuale del tempo di esecuzione consumato da un processo, basato sulla modifica del tempo reale tramite coefficienti.
La decisione su quale sia il prossimo task da mettere in esecuzione si basa sulla scelta dell task con
SUM = SUM + DELTA
t.VRT = t.VRT + DELTA * t.VRTC
Dove SUM
è il tempo totale di esecuzione del task, DELTA
è la durata dell'ultimo quanto consumato dal task e
Si definisce inoltre una variabile
Quando la funzione wake_up
risveglia un task tw
, deve ricalcolare la sua
Risvegliando un task tw
si richiede scheduling se almeno una delle due condizioni è verificata:
L'assegnamento di un paso ad un task si basa sul parametro nice_value
del task. L'utente può assegnare un nice_value
diverso a ciascun task. Questo parametro va da nice_value
maggiore ottiene in proporzione meno tempo di CPU di uno con nice_value
.
Il nice_value
di un task