Processi: Stati, PCB e Scheduling - Tecnologia A4 M1 L01 | Prof. Giagnotti
Tecnologia • Anno 4 • Modulo 1 • Lezione 01
✍ Autore: Prof. Giagnotti

Processi: Stati, PCB e Scheduling

Dal file sul disco al processo vivo in RAM: cosa fa davvero Windows quando apri chrome.exe, come gestisce gli stati, il PCB e la corsa dei thread sulla CPU.

⏱ 55 min 🧠 PCB • Scheduling • Thread
OBIETTIVI DI APPRENDIMENTO
✓Distinguere un programma da un processo e comprendere il concetto di multiprocessing
✓Conoscere gli stati di un processo, le transizioni del ciclo di vita e il ruolo del Process Control Block
✓Confrontare le principali politiche di scheduling (FCFS, SJF, Round Robin, a priorità) calcolandone le metriche
✓Comprendere cos'è un thread, i vantaggi del multithreading e come Windows ne gestisce la schedulazione

Ogni volta che fai doppio click su un eseguibile, il sistema operativo compie un piccolo miracolo che diamo per scontato: trasforma un file inerte in un'entità viva, con memoria, identità, priorità e diritto di chiedere tempo di CPU. Questa è la lezione fondante di Sistemi e Reti del quarto anno.

1. Programmi e processi: la differenza fondamentale

📌 Definizione da ricordare

Programma = file statico su disco. Processo = programma in esecuzione, dinamico, con il suo spazio di indirizzamento, registri, PID e risorse assegnate dal SO.

Il programma è statico e passivo: chrome.exe è una sequenza di byte sul disco. Non fa nulla finché non lo carichi. Il processo è l'esatto opposto: dinamico e attivo. Il SO gli cuce addosso 4 aree di memoria — codice (read-only), dati, heap (malloc/new), stack (variabili locali, chiamate).

💬 Tip del docente – tecnologia concreta

Io ho pensato di fare così per farvelo ricordare all'interrogazione: aprite Task Manager → Dettagli. Se aprite 3 volte Notepad++ vedrete 3 PID diversi, stesso file .exe. Io lo farei così per spiegarlo alla Maturità: "Il programma è la ricetta nel cassetto, il processo è quando sto cucinando davvero, con pentole (RAM) accese e timer (CPU) che gira". Se dite solo "sono la stessa cosa" vi bocciano la domanda sul PCB.

🎯 Esempio in classe – chrome.exe x3

Stesso file C:\Program Files\Chrome\chrome.exe. Tre doppie finestre = tre processi separati, tre stack, tre PID. Se uno crasha, gli altri restano su. Questo isolamento è il motivo per cui il SO preferisce i processi ai semplici programmi.

2. Multiprocessing, multiprogrammazione e multitasking

Una CPU single-core esegue UNA istruzione alla volta. Come sembra che ne faccia 50? Con il time-sharing: assegna a ogni processo un quantum di 2-10 ms, poi context switch. Velocissimo da sembrare parallelo.

TermineSignificatoObiettivo / Quando
MultiprogrammazionePiù processi residenti in RAM: se uno si blocca su I/O, la CPU passa ad un altroMassimizzare utilizzo CPU (anni '60)
Multitasking / Time-sharingSwitch frequentissimi (quantum piccoli) per dare illusione di simultaneità all'utenteReattività verso l'utente
MultiprocessingPiù core/CPU fisiche: vero parallelismo, 8 core = 8 processi davvero simultaneiThroughput reale
💬 Tip del docente

Io ho pensato di fare così quando correggo le verifiche: se confondete multiprogrammazione con multiprocessing vi metto 1 punto in meno. Io lo farei così per ricordarlo: "Multiprogrammazione = più programmi in RAM, Multiprocessing = più CPU reali". Oggi convivono: su ogni core c'è time-sharing, tra core c'è parallelismo vero. Guardate Task Manager > Prestazioni > CPU: vedete i core logici che schizzano.

⚠️ Errore comune – context switch non gratis

Ogni cambio di contesto costa: salvare registri, PC, stack pointer del PCB uscente e caricare quelli entranti. Quantum troppo piccolo = più reattività ma più overhead. Quantum troppo grande = effetto convoglio. È il compromesso che Windows deve tarare.

3. Il ciclo di vita: gli stati di un processo

Un processo non è mai sempre RUNNING. Lo scheduler lo sposta tra 5 stati ben definiti:

NEW READY RUNNING TERMINATED WAITING ammesso dispatch interrupt / quantum scaduto exit richiesta I/O I/O completato
StatoCosa significa davvero
NewCreato, il SO sta allocando PCB, pagine, handle. Non ancora in ready queue.
ReadyIn RAM, tutto pronto, aspetta solo la CPU. Sta nella ready queue.
RunningIstruzioni effettivamente sul core in questo istante. Monocore = 1 solo Running.
Waiting / BlockedBloccato su evento esterno (disco, rete, mutex). Non consuma CPU.
TerminatedFinito. Risorse rilasciate, resta zombie finché il padre non fa wait() sul suo exit code.
🎯 Esempio – perché Waiting è fondamentale

Apri un file di 2GB. Il processo chiede lettura. Se restasse in Running sprecherebbe CPU ad aspettare il disco. Passa in Waiting, lo scheduler dà la CPU a Chrome, Teams, etc. Quando il disco finisce, interrupt → I/O completato → torna Ready. Così non sprechi cicli.

4. Il Process Control Block (PCB)

📌 Definizione da esame – PCB

Il PCB è la carta d'identità del processo: la struttura dati con cui il SO congela e ripristina esattamente un processo. Contiene PID, stato, PC, registri, priorità, memoria, file aperti.

Campo del PCBContenuto praticoPerché serve nel vostro lab
PIDID univoco (es. 4256)Per kill, debug, analisi con Process Explorer
StatoNew/Ready/Running/Waiting/TerminatedDetermina in quale coda metterlo
Program CounterProssima istruzione EIP/RIPSenza, al rientro ripartiresti da capo
Registri CPUEAX, EBX, SP, flags...Context switch = salva/ripristina questi
Info schedulingPriorità, puntatori ready queueDecide chi vince la CPU
MemoriaPage table base, limitiIsolamento tra processi
File/I/OHandle file, socketChiusura risorse su Terminated
💬 Metodo Giagnotti – come spiegarlo

Io ho pensato di fare così a lezione di Tecnologia: vi faccio vedere Process Hacker, aperto su chrome. Clicco su un processo e vi mostro: PID, threads, handles. Io lo farei così all'interrogazione: "Prof, il PCB è come il salvataggio di un videogioco: se staccate la corrente (interrupt), quando riaccendete (dispatch) ripartite esattamente da dove eravate, perché avevate salvato tutto". Se dite questa frase, vi do il mezzo punto in più.

⚠️ Attenzione – costo PCB

Più il PCB è grande, più il context switch costa tempo di CPU buttato in salvataggi. Ecco perché i thread sono "leggeri": il loro PCB salva solo registri e stack, non tutta la memoria virtuale.

5. Le politiche di scheduling

Ready queue piena, CPU libera: chi scegli? Lo decide lo short-term scheduler. Non esiste l'algoritmo perfetto, solo compromessi.

AlgoritmoCome funzionaPro / Contro da interrogazione
FCFS First-Come First-ServedNon preemptive, FIFO fino a fineSemplicissimo, ma effetto convoglio: P lungo blocca tutti
SJF Shortest Job FirstSceglie burst più breve (stimato)Ottimo tempo medio attesa, ma serve predizione e causa starvation processi lunghi
Round RobinFCFS + quantum q. Se non finisce, torna in codaEquo, reattivo. q piccolo = tanti switch, q grande = torna FCFS
A prioritàPriorità numerica esterna, preemptive o noGestisce urgenze, ma starvation priorità basse → serve aging

Calcolo metriche: l'esempio che esce sempre

P1=24ms, P2=3ms, P3=3ms, arrivano tutti a t=0 in ordine P1,P2,P3.

FCFS

Tempo medio attesa

P1 0ms, P2 24ms, P3 27ms → media = (0+24+27)/3 = 17ms. P2 e P3 lentissimi per colpa di P1.

SJF

Ottimo teorico

Ordine P2,P3,P1 → attese: P2 0, P3 3, P1 6 → media = 3ms. Stratosferico, ma devi conoscere le durate prima.

🎯 Round Robin q=4ms – calcoliamo insieme

Timeline: 0-4 P1 (rimangono 20), 4-7 P2 finisce (attesa 4), 7-10 P3 finisce (attesa 7), 10-30 P1 finisce (attesa = 4+3 =7? No: intervalli non-running = 6ms totali perché tra 4-10 non gira). Attese: P1 6ms, P2 4ms, P3 7ms → media ≈5,7ms. Più equo: P2/P3 completano entro 10ms invece di aspettare 24+.

⚠️ Limite grave – starvation & aging

SJF e priorità puri: se arrivano sempre processi brevi/alta priorità, quello lungo/bassa priorità muore di fame. Soluzione: aging = priorità effettiva cresce con attesa. Windows lo fa con priority boost.

💬 Trucco verifica Tecnologia

Io ho pensato di fare così per la verifica scritta: vi do 3 processi con burst e vi chiedo FCFS vs RR. Io lo farei così: disegnate la timeline su carta, segnate ogni quantum, NON fate a mente. L'errore più stupido che vedo ogni anno è sommare i burst invece dei tempi di attesa. Ricordate: tempo di attesa = tempo in Ready, non tempo totale.

6. Il thread: un processo che si moltiplica

📌 Definizione thread

Thread = flusso leggero dentro un processo. Ha PC, registri, stack suoi. Condivide codice, dati globali, heap, file aperti con gli altri thread dello stesso processo.

Browser: un thread rendering, uno JS, uno network → stesso processo, stessa cache, ma corrono paralleli. Perché thread e non processi? Costo.

CaratteristicaProcesso pesanteThread leggero
MemoriaIsolata, propria page tableCondivisa nello stesso processo
ComunicazioneIPC lenta (pipe, socket, shared mem)Diretta via variabili condivise (veloce)
Costo creazioneAlto: copia spazio indirizzamentoBasso: riusa spazio
Context switchPesante (PCB completo)Leggero (solo registri+stack)
CrashIsolatoUn thread buca tutto il processo
01 · VANTAGGI

4 motivi per multithreading

Reattività UI non si blocca, Condivisione no duplicazione RAM, Economicità creazione/switch rapidi, Scalabilità vera su multi-core.

02 · RISCHIO

Race condition

2 thread fanno contatore++ da 0. Leggono entrambi 0, scrivono entrambi 1 → risultato 1 invece di 2. Serve mutex/semaforo (prossima lezione).

⚠️ Pericolo Tecnologia – race

Condividere memoria senza sincronizzazione è come due persone che modificano lo stesso file Google Docs offline e poi sincronizzano: l'ultimo sovrascrive. In verifica: se vedete "variabile condivisa senza mutex" rispondete sempre race condition.

💬 Consiglio Maturità

Io ho pensato di fare così per l'orale: portate l'esempio del browser multithread. Io lo farei così: "Prof, se il thread JS si blocca su un ciclo infinito, la scheda si freeza ma il processo browser può ancora chiuderla perché il thread UI è separato". Così dimostrate di aver capito isolamento parziale vs processi.

7. Multithreading e scheduling in Windows

Windows: ogni processo nasce con almeno 1 thread primario. Ne può creare altri con Win32 API. Scheduler preemptive a priorità: vince sempre il thread Ready con priorità numerica più alta, anche interrompendo quello Running.

📌 32 livelli di priorità

Da 0 (zero page thread) a 31 (real-time). Processo ha 6 classi: Idle, Below Normal, Normal, Above Normal, High, Realtime. Thread ha priorità relativa dentro la classe (Idle → Time-critical). Effettiva = classe + relativa.

Stato thread WindowsSignificato
ReadyIn coda, aspetta scheduler
StandbyScelto come prossimo su quel core
RunningSta girando sulla CPU ora
WaitingAspetta I/O, evento, timer, mutex
TerminatedFinito, handle chiudibile
🎯 Priority boost – perché Windows sembra reattivo

Thread esce da Waiting (es. lettura disco finita) → riceve bonus temporaneo di priorità, gira subito, poi bonus decade ogni quantum. Così l'app che stava caricando torna subito viva.

C · Win32 API · CreateThread + Priority
#include <windows.h> #include <stdio.h> DWORD WINAPI StampaMessaggio(LPVOID param) { printf("Thread in esecuzione, ID: %lu\n", GetCurrentThreadId()); return 0; } int main() { HANDLE hThread = CreateThread( NULL, // sicurezza default 0, // stack default StampaMessaggio, // start routine NULL, // parametro 0, // avvia subito NULL ); SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); WaitForSingleObject(hThread, INFINITE); // Waiting finché thread termina CloseHandle(hThread); return 0; }
💬 Tip lab Tecnologia

Io ho pensato di fare così in lab: compilatelo con x64 Native Tools, aprite Process Explorer e guardate il thread nascere. Io lo farei così per farlo sembrare vostro: spiegate che WaitForSingleObject mette il chiamante in Waiting senza busy-wait, quindi zero CPU sprecata. Nelle app moderne si usa thread pool (QueueUserWorkItem) per non creare/distruggere thread ogni volta: riuso = meno overhead.

8. Verifica e laboratorio mentale

🔬 Attività – carta e penna (da saper fare senza PC)

Esercizi che escono in verifica scritta, 15 minuti:

  1. Disegna il diagramma New→Ready→Running→Waiting→Terminated con le 5 frecce etichettate (ammesso, dispatch, interrupt, I/O request, I/O completato, exit).
  2. Dati P1=10ms, P2=1ms, P3=2ms: calcola tempo medio attesa con FCFS e con RR q=2ms. Spiega dove conviene RR.
  3. Spiega perché il PCB rende costoso il context switch tra processi e meno costoso quello tra thread.
  4. Codice: 2 thread fanno counter++ 1000 volte senza mutex. Quale valore finale ti aspetti? Perché può essere <2000?
  5. Windows: un thread Normal con priorità Above Normal appena uscito da Waiting. Cosa fa il priority boost e perché?
✅ Soluzione ragionata – chiave

1) Guardate svg sopra. 2) FCFS: 0+10+11=21/3=7ms. RR q2: timeline 0-2 P1,2-3 P2 fine(attesa2),3-5 P3 fine(attesa3),5-13 P1 → attese P1 3ms, P2 2ms, P3 3ms → media 2.66ms → RR vince su reattività. 3) PCB processo salva page table, file table; thread solo registri/stack → meno byte copiati. 4) Race: read-modify-write non atomico, incremento perso. Valore atteso <2000, non deterministico. 5) Boost temporaneo, poi decade → reattività percepita, poi torna a base.

🐙 Laboratori Pratici

Vuoi passare all'azione? Accedi alla repository ufficiale GitHub del corso per scaricare i file dei laboratori pratici in formato .md.

Vuoi consultare la sezione dedicata ai laboratori sul sito? Accedi cliccando il pulsante qui sotto.

📊 Sezione dedicata ai Laboratori
✓Programma ≠ Processo: file statico vs entità viva con PID, memoria, stato.
✓Multiprogrammazione / Time-sharing / Multiprocessing = 3 livelli: più processi in RAM, switch rapidi, core multipli reali.
✓5 stati: New, Ready, Running, Waiting, Terminated + transizioni ammesso/dispatch/interrupt/I-O/exit.
✓PCB = salvataggio completo: PID, PC, registri, priorità, page table, handle. Context switch = salva PCB vecchio + carica nuovo.
✓Scheduling: FCFS facile ma convoglio, SJF ottimo media ma starvation, RR equo/reattivo, priorità + aging.
✓Thread: flusso leggero, condivide memoria, comunicazione veloce, creation/switch cheap, ma race condition se no mutex.
✓Windows: 32 priorità, 6 classi processo, priority boost dopo Waiting, CreateThread + thread pool per efficienza.