# Introduzione: sistemi multi-tasking

Gli OS in grado di eseguire piu' di un processo in contemporanea sono chiamati sistemi *multi-tasking*. La vera simultaneita' si verifica solamente quando sono disponibili piu' CPU, ma anche i sistemi a processore singolo possono simularla, passando da un processo ad un altro molto rapidamente. Infatti, solo un processo alla volta puo' utilizzare la CPU.

## Il Linux scheduler

Lo scheduler *organizza la coda dei processi*. Esistono due tipi principali di criteri di pianificazione (*scheduling*):

- *politiche in tempo reale*: *i processi vengono eseguiti in base ai loro valori di priorita'*. Se un processo con priorita' maggiore diventa pronto per essere eseguito, un processo meno importante viene interrotto e il processo con priorita' piu' alta assume il controllo della CPU. Un processo con priorita' inferiore otterra' il controllo della CPU solo quando i processi con priorita' maggiore saranno inattivi o in attesa di risposte hardware. Qualsiasi processo in tempo reale ha una priorita' maggiore di un processo normale
- *politiche normali*: i processi normali hanno tutti lo stesso valore di priorita', ma le politiche normali possono definire delle regole di priorita' d'esecuzione utilizzando il *nice value*

## Priorita'

In Linux:

- *Processi in tempo reale*: priorita' statiche da 0 a 99
- *Processi normali*: priorita' statiche da 100 a 139. Priorita' standard 120

Valori inferiori significano priorita' maggiore. 

La priorita' puo' essere verificata col comando `ps -el`:

```bash
 > ps -el
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0       1       0  0  80   0 -  6093 -      ?        00:00:05 systemd
1 S     0       2       0  0  80   0 -     0 -      ?        00:00:00 kthreadd
1 S     0       3       2  0  80   0 -     0 -      ?        00:00:00 pool_workqueue_release
1 I     0       4       2  0  60 -20 -     0 -      ?        00:00:00 kworker/R-rcu_gp
1 I     0       5       2  0  60 -20 -     0 -      ?        00:00:00 kworker/R-sync_wq
1 I     0       6       2  0  60 -20 -     0 -      ?        00:00:00 kworker/R-slub_flushwq
```

- La colonna `PRI` indica la priorita' statica assegnata dal Kernel. Per ragioni storiche, le priorita' visualizzate da `ps` vanno da -40 a 99, quindi la priorita' effettiva si ottiene aggiungendo 40 al numero visualizzato (80+40=120).

Anche tramite `top` e' possibile monitorare la priorita' dei processi. `top` sottrae il valore di priorita' di 100, per rendere tutte le priorita' in tempo reale *negative*. Le priorita' normali, pertanto, vanno da 0 a 39.

Riepilogando:

- linux: 0 a 139
- `ps`: -40 a 99 (-40)
- `top`: -100 a 39 (-100)

## Niceness

I numeri di *niceness* vanno da -20 (priorita' alta) a 19 (maggior gentilezza, priorita' bassa). Ogni processo normale inizia con un valore di *niceness* di 0 (priorita' 120). 

- La colonna `NI`, nell'output di `ps` indica il valore di *niceness*. Solo l'utente root puo' diminuire la *niceness* di un processo al di sotto dello zero.

E' possibile avviare un processo con una priorita' non standard col comando `nice`:

```bash
nice -n 5 tar czf backup.tar.gz /home
```

Il comando `renice` puo' essere usato per modificare la priorita' di un processo in esecuzione: `renice -10 -p PID`. Le opzioni `-g` e `-u` sono usate per modificare rispettivamente tutti i processi di un gruppo o di un utente specifico. Ad esempio con `renice -5 -g users` la *niceness* dei processi degli utenti appartenenti al gruppo *users* sara' aumentata di 5.

La *niceness* puo' essere modificata anche con `top`, premendo il tasto `R`, quindi il PID del processo.