Namespace
I namespace isolano le risorse in modo che i processi posano vedere la propria versione del sistema. Ogni namespace isola un tipo di risorse. Es:
- PID namespace → separate process trees
- NET namespace → separate network interfaces and routing
- MNT namespace → separate filesystem mount points
- UTS namespace → separate hostname
- IPC namespace → separate shared memory/message queues
- USER namespace → separate user IDs
differenza con os virtualizzato:
- si puo fare boot (macchine virtuali)
- tutte queste pseudo macchine viirtuali (namespace) condividono il kernel con l'os
System call specifiche:
- Clone: crea un nuovo processo, con opportune flag vengono creati nuovi namespace e il processo creato farà parte di questi namespace (e.g. CLONE_NEWNET, CLONE_NEWPID…)
- Setns: connette il processo chiamante a namespace esistenti
- Unshare: muove il processo chiamante in un nuovo namespace
(I namespace servono per creare container): Un container e':
- Un gruppo di processi che tramite namespace “vede”:
- Una immagine di file system privata
- Una propria configurazione di rete
- Limiti di accesso alle risorse (cgroup)
- Gestito da meccanismi di amministrazione a run-time (docker, runc, containerd)
Progettazione so
Definizione del problema
- definire gli obiettivi del sistema che si vuole realizzare
- definire i "costraint" entro cui si opera
- La progettazione sarà influenzata:
- al livello più basso, dal sistema hardware con cui si va ad operare
- al livello più alto, dalle applicazioni che devono essere eseguite dal sistema operativo
- A seconda di queste condizioni, il sistema sarà…
- batch, time-shared, single-user, multi-user, distribuito, general-purpose, real-time, etc…
Scheduler, processi e thread
Un sistema operativo è un gestore di risorse (processore, memoria principale e secondaria, dispositivi)
Per svolgere i suoi compiti, un sistema operativo ha bisogno di strutture dati per mantenere informazioni sulle risorse gestite Queste strutture dati comprendono:
- tabelle di memoria
- tabelle di I/O
- tabelle del file system
- tabelle dei processi

Processi
Qual è la manifestazione fisica di un processo?
- il codice da eseguire (segmento codice)
- i dati su cui operare (segmenti dati)
- uno stack di lavoro per la gestione di chiamate di funzione, passaggio di parametri e variabili locali
- un insieme di attributi contenenti tutte le informazioni necessarie per la gestione del processo stesso
- incluse le informazioni necessarie per descrivere i punti 1-3
Questo insieme di attributi prende il nome di descrittore del processo (process control block, PCB)
PCB
I PCB e' la tabella per la gestion dei processi:
- contiene i descrittori dei processi (PCB)
- ogni processo ha un PCB associato
E' possibile suddividere le informazioni contenute nel descrittore in tre aree:
- info di identificazione di processo
- info di stato di processo]
- info di controllo del processo
Informazioni di identificazione di un processo identificatore di processo (process id, o pid)
- può essere semplicemente un indice all'interno di una tabella di processi
- può essere un numero progressivo; in caso, è necessario un mapping tra pid e posizione del relativo descrittore
- molte altre tabelle del s.o. utilizzano il process id per identificare un elemento della tabella dei processi
identificatori di altri processi logicamente collegati al processo
- ad esempio, pid del processo padre
id dell'utente che ha richiesto l'esecuzione del processo
Informazioni di stato del processo
- registri generali del processore
- registri speciali, come il program counter e i registri di stato
Informazioni di controllo del processo:
- Informazioni di scheduling
- stato del processo (in esecuzione, pronto, in attesa)
- informazioni particolari necessarie dal particolare algoritmo di schuduling utilizzato (priorità, puntatori per la gestione delle code)
- identificatore dell'evento per cui il processo è in attesa
- informazioni di gestione della memoria - Informazioni di configurazione della MMU, es. puntatori alle tabelle delle pagine, etc.
- informazioni di accounting
- tempo di esecuzione del processo
- tempo trascorso dall'attivazione di un processo
- informazioni relative alle risorse
- risorse controllate dal processo, come file aperti, device allocati al processo
- informazioni per interprocess communication (IPC)
- stato di segnali, semafori, etc.
In linux la struttura dati che contiene il PCB e' la struct task
Scheduler
e' la componente piu importante del kernel. Gestisce l'avvicendamento dei processi
- quando viene richiamato decide quale deve essere in exec
- intervien quando viene richiesta una op di I/O e quando un op di io ternima.
Nota: il termine scheduler viene usato utilizzato anche in altri ambiti (es. scheduler del disco), noi ci riferiamo allo scheduler del so
Schedule: è la sequenza temporale di assegnazioni delle risorse da gestire ai richiedenti Scheduling: è l'azione di calcolare uno schedule Scheduler: è la componente software che calcola lo schedule
Mode switching e context switching
Tutte le volte che avviene un interrupt il processore e' soggetto a mode switching (mod utente -> mod supervisore)
Durante la gestione dell'interrupt:
- vengono intraprese le opportune azioni per gestire l'evento
- viene chiamato lo scheduler
- se lo scheduler decide di eseguire un altro processo, il sistema e' soggetto a context switching
Operazioni durante un context switching
- lo stato del processo attuale viene salvato nel PCB corrispondente
- lo stato del processo selezionato per l'esecuzione viene caricato dal PCB nel processore
so salva il pcb di p1, carica il codice del pcb p2 e lo esegue. Infine p2 lancia un interrupt e si torna a p1
Dentro inizialize c'e' il main
Stati dei processi:
- Running: il processo è in esecuzione
- Waiting: il processo è in attesa di qualche evento esterno (e.g., completamento operazione di I/O); non può essere eseguito
- Ready: il processo può essere eseguito, ma attualmente il processore è impegnato in altre attività

utte le volte che un processo entra nel sistema, viene posto in una delle code gestite dallo scheduler

Gerarchia di processi
Nella maggior parte dei sistemi operativi i processi sono organizzati in forma gerarchica. Quando un processo crea un nuovo processo, il processo creante viene detto padre e il creato figlio. Si viene così a creare un albero di processi
Motivazioni:
- semplificazione del procedimento di creazione di processi
- non occorre specificare esplicitamente tutti i parametri e le caratteristiche
- ciò che non viene specificato, viene ereditato dal padre

Processi e Thread
La nozione di processo discussa in precedenza assume che ogni processo abbia una singola “linea di controllo”
- per ogni processo, viene eseguite una singola sequenza di istruzioni
- un singolo processo non può eseguire due differenti attività contemporanemente Esempi:
- scaricamento di due differenti pagine in un web browser
- inserimento di nuovo testo in un word processor mentre viene eseguito il correttore ortografico
Tutti i sistemi operativi moderni
- supportano l’esistenza di processi multithreaded
- in un processo multithreaded esistono molte “linee di controllo”, ognuna delle quali può eseguire una diversa sequenza di istruzioni
Esempi:
- Associando un thread ad ogni finestra aperta in un web browser, è possibile scaricare i dati in modo indipendente
Un thread è l’unità base di utilizzazione della CPU
Ogni thread possiede
- la propria copia dello stato del processore
- il proprio program counter
- uno stack separato
I thread appartenenti allo stesso processo condividono:
- codice
- dati
- risorse di I/O

Benefici dei thread:
- condivisione di risorse
- i thread condividono lo spazio di mem e le risorse allocate degli altri thread dello stesso processo
- condividere info tra thread logicamente correlati rende piu semplice l'implementazione di certe applicazioni
Es: web browser (condivisione dei param di config tra i vari thread)
- Economia:
- allocare mem e risorse pepr creare nuovi processi e' costoso
- fare context switching fra diversi processi e' costoso
- gestire thread e' meno costoso (es. creare un thread in solaris richiede 1/30 del tempo richiesto per creare un processo nuovo)
in ogni caso, abbiamo bisogno di processi distinti per applicazioni differenti
Multithreading: implementazione
Due modi:
- user thread (livello utente)
- kernel thread (livello kernel)
Oggi vengono usati di piu i kernel thread
User thread
Gli user thread vengono supportati sopra il kernel e vengono implementati dsa una thread library a livello utente
Vantaggi:
- implementazione molto efficiente
Svantaggi:
- se il kernel e' single threaded qualsiasi user thread che effettua una chiamata a sistema bloccante (es io) causa il blocco dell'intero processo
Kernel thread
Vengono supportati direttamente dal sistema operativo
Vantaggi:
- poiche e' il kernel a gestire lo scheduling dei thread, se un thread segue op di io il kernel puo' selezionare un altro thread in attesa di essere eseguito
Svantaggi:
- implementazione piu lenta –> richiede un passaggio da livello utente a livello supervisore
Modelli di multithreading
Molti sistemi usano entrambe i tipi di thread, creando vari tipi di modelli di multithreading
- Many-to-One
- One-to-One
- Many-to-Many
Many-to-One Multithreading
Un certo numero di user thread vengono mappati su un solo kernel thread
Modello generalmente adottato da s.o. che non supportano kernel thread multipli

One-to-One Multithreading
Ogni user thread viene mappato su un kernel thread
Può creare problemi di scalabilità per il kernel

Many-to-Many Multithreading
Riassume i benefici di entrambe le architetture
Supportato da Solaris, IRIX, Digital Unix

Scheduling
Per rapp uno schedule si usano i diagrammi di Gantt
in questo esempio, la risorsa (es. CPU) viene utilizzata dal processo P1 dal tempo 0 a t1, viene quindi assegnata a P2 fino al tempo t2 e quindi a P3 fino al tempo t3
Eventi che possono causare un context switch:
- quando un processo passa da stato running a stato waiting (system call bloccante, operazione di I/O)
- quando un processo passa dallo stato running allo stato ready (a causa di un interrupt)
- quando un processo passa dallo stato waiting allo stato ready
- quando un processo termina
Tipi di scheduler
Uno scheduler si dice non-preemptive o cooperativo
- se i context switch avvengono solo nelle cond 1 e 4
- il controllo della risorsa viene trasferito solo se l'assegnatario attuale lo cede volontariamente Uno scheduler si dice preemptive se:
- i context switch possono avvenire in ogni condizione
- è possibile che il controllo della risorsa venga tolto all'assegnatario attuale a causa di un evento
Tutti gli scheduler moderni sono preemptive.
Vantaggi dello scheduling cooperativo
- non richiede alcuni meccanismi hardware come ad esempio timer programmabili Vantaggi dello scheduling preemptive
- permette di utilizzare al meglio le risorse
Criteri di scelta di uno scheduler
Utilizzo della risorsa (CPU)
- percentuale di tempo in cui la CPU è occupata ad eseguire processi
- deve essere massimizzato Throughput
- numero di processi completati per unità di tempo
- dipende dalla lunghezza dei processi
- deve essere massimizzato
Tempo di turnaround
- tempo che intercorre dalla sottomissione di un processo alla sua terminazione
- deve essere minimizzato
Tempo di attesa
- il tempo trascurso da un processo nella coda ready
- deve essere minimizzato
- Tempo di risposta
- tempo che intercorre fra la sottomissione di un processo e il tempo di prima risposta
- particolarmente significativo nei programmi interattivi, deve essere minimizzato
Vita di un processo:

Durante l'esecuzione di un processo:
- si alternano periodi di attività svoltedalla CPU (CPU burst)…
- …e periodi di attività di I/O (I/O burst) I processi:
- caratterizzati da CPU burst molto lunghi si dicono CPU bound
- caratterizzati da CPU burst molto brevi si dicono I/O bound
Algoritmi:
- First Come, First Served
- Shortest-Job First
- Shortest-Next-CPU-Burst First
- Shortest-Remaining-Time-First
- Round-Robin
First Come, First Served (FCFS)
Algoritmo
- il processo che arriva per primo, viene servito per primo
- politica senza preemption
Implementazione
- semplice, tramite una coda (politica FIFO)
Problemi
- elevati tempi medi di attesa e di turnaround
- processi CPU bound ritardano i processi I/O bound
Esempio:
- ordine di arrivo: P1, P2, P3
- lunghezza dei CPU-burst in ms: 32, 2, 2
- Tempo medio di turnaround: (32+34+36)/3 = 34 ms
- Tempo medio di attesa: (0+32+34)/3 = 22 ms

Supponiamo di avere:
- un processo CPU bound
- un certo numero di processi I/O bound
- i processi I/O bound si "mettono in coda" dietro al processo CPU bound, e in alcuni casi la ready queue si puo svuotare
- Convoy effect
Shortest Job First (SJF)
la CPU viene assegnata al processo ready che ha la minima durata del CPU burst successivo (politica senza preemption)
Esempio
- Tempo medio di turnaround: (0+2+4+36)/3 = 7 ms
- Tempo medio di attesa: (0+2+4)/3 = 2 ms
L'algoritmo SJF
- è ottimale rispetto al tempo di attesa, in quanto è possibile dimostrare che produce il minor tempo di attesa possibile
- ma è impossibile da implementare in pratica!
- è possibile solo fornire delle approssimazioni
- non possiamo conoscere la lunghezza del prossimo CPU burst…. ma conosciamo la lunghezza di quelli precedenti
Calcolo approssimato della durata del CPU burst:
- basata su media esponenziale dei CPU burst precedenti
- sia tn il tempo dell'n-esimo CPU burst e тn la corrispondente previsione; тn+1 può essere calcolato come segue:
Media esponenziale
- svolgendo la formula di ricorrenza, si ottiene da cui il nome media esponenziale

Shortest Job First "approssimato" esiste in due versioni:
- non preemptive
- il processo corrente esegue fino al completamento del suo CPU burst
- preemptive - il processo corrente può essere messo nella coda ready, se arriva un processo con un CPU burst più breve di quanto rimane da eseguire al processo corrente
- "Shortest-Remaining-Time First"