Il processo รจ unโistanza di un programma in esecuzione su un computer e rappresenta una delle unitร fondamentali di gestione delle risorse da parte di un sistema operativo. Quando un programma viene eseguito, il sistema operativo crea un processo per esso, fornendogli le risorse necessarie, come CPU, memoria, accesso ai file e altri dispositivi.
Osservazione: differenza tra processo e programma
La differenza tra il concetto di processo e quello di programma รจ fondamentale in informatica, poichรฉ indicano concetti distinti legati allโesecuzione di unโapplicazione:
Un programma รจ un insieme di istruzioni scritte in un linguaggio di programmazione, che descrive quali operazioni un computer deve eseguire. ร unโentitร passiva e rappresenta il codice sorgente o il codice binario di unโapplicazione, che viene memorizzato in un file su disco (es. un file eseguibile .exe su Windows, oppure un documento contenente codice sorgente scritto in un linguaggio di programmazione come Python o C). Un programma non fa nulla da solo finchรฉ non viene avviato.
Un processo รจ unโistanza di un programma in esecuzione sulla memoria centrale (RAM). ร unโentitร attiva che include il codice del programma, lo stato della CPU (come il contatore del programma e i registri), lo spazio di memoria (segmento di testo e dei dati, stack e heap) e le risorse utilizzate dal programma. Quando un programma viene eseguito, il sistema operativo crea un processo per gestirne lโesecuzione.
Ecco una tabella riassuntiva:
Caratteristica
Programma
Processo
Definizione
Un insieme di istruzioni memorizzate su disco
Unโistanza di un programma in esecuzione
Stato
Entitร passiva
Entitร attiva
Memoria
Non usa memoria attiva
Utilizza memoria (segmento di testo e dei dati, stack e heap)
Esecuzione
Non รจ in esecuzione
In esecuzione
Durata
Permanente fino a quando รจ cancellato o modificato
Temporanea, esiste solo durante lโesecuzione
Gestione
Non richiede gestione attiva
Gestito dal sistema operativo (CPU, memoria, I/O)
Relazione
Un programma puรฒ generare piรน processi
Ogni processo รจ basato su un programma
Osservazione: piรน processi per lo stesso programma
Sebbene due processi siano associabili allo stesso programma, sono tuttavia da considerare due sequenze dโesecuzione distinte. Per esempio, lโutente puรฒ aprire piรน finestre dello stesso browser e, di conseguenza, generare piรน istanze dello stesso programma: ciascuna istanza รจ un diverso processo e, benchรฉ le sezioni di memoria contenenti il codice siano equivalenti, in realtร quelle dei dati, dellโheap e dello stack sono diverse. ร inoltre usuale che durante la propria esecuzione un processo generi altri processi.
1 - Il PCB e le informazioni sul processo
Definizione: blocco di controllo del processo (PCB)
Il blocco di controllo del processo (in inglese PCB, Process Control Block) รจ una struttura dati fondamentale utilizzata dal sistema operativo per memorizzare nella RAM tutte le informazioni relative a un processo dal momento della sua inizializzazione e aggiornato durante lโintero ciclo di vita del processo.
Le informazioni contenute in un PCB variano a seconda delle implementazioni nei vari sistemi operativi, ma in generale sono presenti:
Identificatore del processo (in inglese PID, Process ID): un numero intero univoco assegnato al processo dal sistema operativo. Questo identificatore viene utilizzato per distinguere il processo dagli altri processi attivi.
Program Counter (abbreviato in PC): il valore contenuto nel Program Counter della CPU nel momento in cui il processo รจ stato interrotto, per consentire di riprendere poi lโesecuzione correttamente dallโultima istruzione eseguita prima dellโinterruzione stessa. Non viene aggiornato di continuo, ma solo nel momento in cui si effettua il cambio di contesto, perchรฉ altrimenti sarebbe inutile e poco efficiente tenerlo sincronizzato.
Stato dei registri della CPU: i valori contenuti in alcuni registri della CPU di uso comune (es. accumulatori, puntatori allo stack, registri di uso generale) nel momento in cui il processo รจ stato interrotto. Come per il Program Counter, non vengono aggiornati di continuo, ma solo nel momento in cui si effettua il cambio di contesto, perchรฉ altrimenti sarebbe inutile e poco efficiente tenere tutti i valori sincronizzati.
Informazioni sulla gestione della memoria: dati su come la memoria รจ allocata al processo, come indirizzi di base e limiti di memoria del processo, oppure tabelle di paginazione o segmentazione, nel caso il sistema operativo utilizzi tecniche di gestione della memoria virtuale.
Informazioni di I/O: un elenco dei dispositivi di input/output utilizzati dal processo (es. file aperti, dispositivi hardware come stampanti, reti) e file descriptor che fanno riferimento ai file aperti dal processo.
Informazioni di schedulazione: un elenco delle informazioni utili alla schedulazione dei processi, come:
Prioritร del processo: indica lโimportanza relativa del processo rispetto agli altri.
Tempo di esecuzione accumulato: il tempo che il processo ha trascorso in esecuzione.
Algoritmo di schedulazione utilizzato: se il sistema operativo utilizza diverse politiche di schedulazione, nel PCB viene specificata quale viene usata.
Informazioni di accounting: dati utilizzati per tenere traccia del tempo CPU consumato dal processo, della quantitร di risorse utilizzate e di eventuali statistiche di utilizzo, utili per la fatturazione o il monitoraggio delle prestazioni.
Informazioni sui segnali: un elenco dei segnali che il processo puรฒ ricevere e le relative azioni da eseguire al ricevimento di un segnale (ad esempio, terminare il processo o ignorare il segnale).
1.1 - Stato di un processo
Definizione: stato di un processo
Lo stato di un processo rappresenta la condizione in cui si trova un processo in un dato momento durante la sua esistenza nel sistema operativo. Serve a gestire i processi in modo efficiente, garantendo che la CPU venga utilizzata in modo ottimale senza che rimanga inattiva: per esempio, quando un processo รจ in attesa, il sistema operativo puรฒ assegnare la CPU a un altro processo giร pronto per essere eseguito.
Vediamo ora la definizione completa di ogni stato.
Definizione: stato new (nuovo)
Un processo entra nello statonew (nuovo) non appena viene creato e ci rimane finchรฉ non sarร pronto per essere eseguito. Durante questa fase di inizializzazione vengono assegnate risorse come memoria e PID.
Definizione: stato ready (pronto)
Un processo entra nello statoready (pronto) quando รจ pronto per essere eseguito ma sta aspettando che la CPU diventi disponibile perchรฉ รจ occupata da altri processi.
Definizione: stato running (in esecuzione)
Un processo รจ nello statorunning (in esecuzione) quando utilizza la CPU e le sue istruzioni vengono eseguite.
Definizione: stato waiting (in attesa)
Un processo รจ nello statowaiting (in attesa) (o anche blocked (bloccato) oppure sleeping (dormiente)) quando รจ in attesa di un evento esterno per continuare lโesecuzione, come il completamento di unโoperazione di input/output (I/O), la ricezione di dati o un messaggio.
Definizione: stato terminated (terminato)
Un processo entra nello statoterminated (terminato) quando ha completato la sua esecuzione o รจ stato interrotto in modo anomalo (per esempio, a causa di un errore). In questo stato, tutte le risorse del processo vengono rilasciate e il processo non esiste piรน nel sistema operativo.
1.1.1 - Visualizzazione degli stati correnti dei processi
In UNIX, tramite il comando ps -axjf si puรฒ avere una visualizzazione ad albero della lista di tutti i processi presenti nel sistema (ovverosia presenti nella coda dei processi) e, nella colonna STAT, ogni codice รจ associato a uno stato o una caratteristica del processo ed essi possono essere combinati tra loro:
Codice STAT
Descrizione
S
Sleeping: il processo รจ nello stato sleeping e si trova allโinterno della coda dei processi bloccati in attesa che accada un evento, come un segnale o che un input diventi disponibile.
Disk sleep: il processo รจ in uno stato sleeping non interrompibile e si trova allโinterno della coda dei processi bloccati in attesa che un input o output diventi disponibile.
Zombie: il processo รจ nello stato zombie, ossia รจ terminato ma รจ in attesa di una wait() dal processo padre.
N
Nice: il processo รจ in esecuzione con bassa prioritร .
W
Waiting for paging: il processo รจ in attesa che le pagine di memoria vengano scritte o lette dal disco (raro nei moderni sistemi Linux).
s
Session leader: il processo รจ un leader di sessione (es. una shell che avvia altri processi).
+
Il processo appartiene al gruppo di processi in esecuzione in primo piano (foreground) nel terminale.
l
Il processo รจ multithreaded (usato su alcuni sistemi come Solaris e Linux).
<
Il processo ha una prioritร alta, quindi riceve piรน CPU rispetto ad altri.
1.2 - Identificatore del processo (PID)
Definizione: identificatore del processo (PID)
Lโidentificatore del processo (in inglese PID, Process ID) รจ un numero intero univoco assegnato al processo dal sistema operativo. Questo identificatore viene utilizzato per distinguere il processo dagli altri processi attivi allโinterno del kernel.
1.2.1 - Ottenere i PID tramite getpid() e getppid()
La funzione getpid() รจ una chiamata di sistema utilizzata per ottenere il PID del processo che la usa.
Il suo prototipo รจ il seguente:
#include <unistd.h>pid_t getpid();
dove:
pid_t restituito: PID del processo che ha invocato la funzione.
La funzione getppid() รจ una chiamata di sistema utilizzata per ottenere il PID del processo padre di quello che la usa.
Il suo prototipo รจ il seguente:
#include <unistd.h>ppid_t getppid();
dove:
ppid_t restituito: PID del processo padre del processo che ha invocato la funzione.
Le relazioni tra processi costituiscono una struttura ad albero. Il genitore di ogni processo ha a sua volta un genitore, fino ad arrivare alla radice: il processo init.
Esempio: visualizzazione dei PID del figlio e del padre
Ecco un semplice codice in C per visualizzare il PID del processo che sta eseguendo questo programma (il figlio) e quello del suo processo padre (ossia il processo del terminale che ha eseguito il programma):
#include <stdio.h>#include <unistd.h>int main(int argc, char *argv[]) { printf("Id del processo: %d\n", getpid()); printf("Id del processo padre: %d\n", getppid());}
1.3 - Spazio di memoria
Definizione: spazio di memoria di un processo
Lo spazio di memoria di un processo rappresenta lโinsieme di tutte le aree di memoria allocate per un processo dal sistema operativo e contiene il codice eseguibile, i dati e le strutture necessarie per far funzionare il programma. Ogni processo ha il proprio spazio di memoria isolato, separato da quello degli altri processi, garantendo che un processo non possa accedere o modificare direttamente la memoria di un altro processo: questa separazione migliora la sicurezza e la stabilitร del sistema.
Lo spazio di memoria di un processo รจ solitamente diviso in:
Segmento di codice (o segmento testo): contiene il codice eseguibile del programma, cioรจ le istruzioni che la CPU eseguirร . Il segmento di codice รจ generalmente di sola lettura, per evitare che il codice del programma venga accidentalmente modificato.
Segmento dati: contiene le variabili globali e statiche del programma, divise in:
Dati inizializzati: lโinsieme delle variabili globali e statiche a cui รจ stato assegnato un valore al momento della dichiarazione.
Dati non inizializzati (in inglese BSS, Block Started by Symbol): lโinsieme delle variabili globali e statiche che sono dichiarate ma non esplicitamente inizializzate, quindi non hanno un valore inizialmente definito; in alcuni sistemi operativi vengono inizializzate a zero.
Heap: รจ lโarea della memoria dinamica utilizzata per lโallocazione di memoria a runtime. Quando un programma richiede memoria dinamica (ad esempio tramite funzioni come malloc() in C o new in C++/Java), questa viene allocata nello heap, il quale viene gestito unicamente dal programmatore stesso (cioรจ il programmatore รจ lโunico responsabile della gestione e del rilascio della memoria).
Stack: area di memoria che viene utilizzata per memorizzare variabili locali, parametri di funzione e indirizzi di ritorno da funzioni. Ogni volta che viene chiamata una funzione, un nuovo โframeโ viene aggiunto allo stack, che contiene le informazioni relative a quella particolare chiamata. Quando la funzione termina, lo stack viene โsrotolatoโ e il frame della funzione viene rimosso. Lo stack si espande e si contrae automaticamente durante lโesecuzione del programma, e la sua gestione รจ di solito curata dal compilatore e dal sistema operativo.
Ecco una rappresentazione grafica dello spazio di memoria di un processo:
1.3.1 - Variazione della grandezza dei segmenti di memoria
Si puรฒ notare che le dimensioni dei segmenti di codice e di dati sono fisse, ovvero non cambiano durante lโesecuzione del programma, mentre le dimensioni di stack e heap possono ridursi e crescere dinamicamente durante lโesecuzione:
Ogni volta che si chiama una funzione, viene inserito nello stack una struttura dati detta record di attivazione (in inglese activation record) contenente i suoi parametri, le variabili locali e lโindirizzo di ritorno; quando la funzione restituisce il controllo al chiamante, il record di attivazione viene rimosso dallo stack.
Allo stesso modo, lโheap crescerร quando viene allocata memoria dinamicamente e si ridurrร quando la memoria viene restituita al sistema.
Visto che le sezioni dello stack e dellโheap crescono lโuna verso lโaltra, tocca al sistema operativo garantire che non si sovrappongano.
5 - Concorrenza tra processi
In informatica, la concorrenza รจ la proprietร di un sistema in cui piรน attivitร indipendenti fanno progresso nello stesso intervallo di tempo, condividendo potenzialmente risorse, senza che sia richiesta la loro esecuzione simultanea.
Un singolo processore puรฒ gestire concorrenza tramite interleaving (alternanza rapida tra task).
Lโobiettivo principale รจ la gestione di piรน compiti (reattivitร , organizzazione, correttezza).
Esempio
Un sistema operativo con un solo core che alterna:
un editor di testo
un browser
un processo in background
I processi sono concorrenti, ma non paralleli.
Osservazione:
Un sistema puรฒ essere concorrente ma non parallelo.
Un sistema parallelo รจ sempre anche concorrente (ma non viceversa).
5.1 - Parallelismo
Uno dei modi in cui si puรฒ implementare la concorrenza รจ col parallelismo, ossia eseguendo piรน unitร di elaborazione contemporaneamente.
Definizione: parallelismo
Il parallelismo รจ la capacitร di eseguire piรน processi o thread contemporaneamente. Questo viene gestito dal sistema operativo attraverso tecniche come il multiprocessing e il multithreading. Il parallelismo nei sistemi operativi consente un migliore utilizzo delle risorse della CPU e migliora la reattivitร delle applicazioni.
Definizione: legge di Amdahl
La legge di Amdahl afferma che seย Fย รจ la frazione di un calcolo che รจ parallelizzabile (cioรจ che puรฒ beneficiare dal parallelismo), e (1โF) รจ la frazione che non puรฒ essere parallelizzata, allora lโaumento massimo di velocitร , cioรจ lโaccelerazione a, che si puรฒ ottenere usandoย Nย processori รจ:
a=(1โF)+NFโ1โ
Al tendere del numeroย Nย di processori allโinfinito, lโaccelerazione a tende a 1โF1โ (perchรฉ NFโ tende a 0). In pratica, il rapporto prestazioni/prezzo scende rapidamente al crescere diย N, dato cheย NFโย diventa piccolo rispetto aย (1โF).
Osservazione: quando usare il parallelismo
Dalla legge di Amdahl si puรฒ intuire che il parallelismo รจ utile solamente o per piccoli numeri diย processoriย o per problemi con valori molto bassi diย (1โF). Per fare un esempio, seย (1โF)ย รจ solamente il 10% (cioรจ solo un decimo delle operazioni non sono parallelizzabili), la velocitร del calcolo puรฒ essere al massimo decuplicata, indipendentemente dal valore diย N.
Tipi di parallelismo
Parallelismo dei dati: distribuisce sottoinsiemi degli stessi dati su piรน processi, stessa operazione su ognuno di essi
Esempio: Si consideri, per esempio, lโoperazione di somma dei valori contenuti in un vettore di dimensione N. In un sistema con un singolo core, un thread sommerebbe semplicemente gli elementi da [0] a [N โ 1]. In un sistema dual-core, invece, il thread A, in esecuzione sul core 0, potrebbe sommare gli elementi da [0] a [N/2 โ 1], mentre il thread B, in esecuzione sul core 1, potrebbe sommare gli elementi da [N/2] a [N โ 1]. I due thread sarebbero in esecuzione in parallelo su core di elaborazione distinti.
Parallelismo delle attivitร : distribuisce le attivitร sui core, ognuno dei quali effettua operazioni distinte sugli stessi dati degli altri o su dati diversi.
Esempio: A differenza della situazione precedente, un esempio di parallelismo delle attivitร potrebbe coinvolgere due thread, ciascuno dei quali esegue unโunica operazione statistica sullโarray di elementi. I thread operano ancora in parallelo su core separati, ma ciascuno sta eseguendo unโoperazione diversa
Tuttavia, parallelismo dei dati e parallelismo delle attivitร non sono mutuamente esclusivi, e le applicazioni possono utilizzare un ibrido di queste due strategie.
5.1.1 - Multiprocessing
Definizione: multiprocessing
Il multiprocessing รจ la capacitร di un sistema operativo di implementare il parallelismo tra processi, eseguendoli simultaneamente, ciascuno con il proprio spazio di memoria, consentendo un isolamento e una stabilitร piรน robusti.
Multiprogrammazione
Definizione: multiprogrammazione
La multiprogrammazione รจ una tecnica dei sistemi operativi che consente di mantenere piรน processi in memoria centrale contemporaneamente, alternandone lโesecuzione sulla CPU.
Lโidea di base รจ evitare che la CPU rimanga inattiva: quando un processo in esecuzione si blocca (ad esempio per unโoperazione di I/O), il sistema operativo assegna la CPU a un altro processo pronto. In questo modo si massimizza lโutilizzo del processore e si migliora lโefficienza complessiva del sistema.
ร opportuno distinguere la multiprogrammazione da concetti affini:
Multitasking: spesso usato come sinonimo a livello pratico, ma enfatizza lโalternanza rapida dei processi per garantire reattivitร allโutente;
Multiprocessing: prevede piรน CPU o core che eseguono processi realmente in parallelo;
Multithreading: riguarda la presenza di piรน thread allโinterno dello stesso processo, non piรน processi distinti.
5.2 - Multitasking
Definizione: multitasking
Il multitasking รจ la capacitร di un sistema operativo di eseguire piรน processi in maniera apparentemente simultanea, cioรจ eseguendoli in modo sequenziale con rapidi cambi di contesto che danno allโutente lโimpressione che tutti stiano avanzando contemporaneamente.
I principali vantaggi del multitasking sono:
Miglior utilizzo della CPU: sfrutta al massimo la capacitร del processore eseguendo diverse attivitร , riducendo i tempi di inattivitร della CPU.
Efficienza e produttivitร : permette di eseguire piรน operazioni allo stesso tempo, migliorando la produttivitร , ad esempio facendo girare un programma in background mentre si lavora su un altro.
Esperienza utente migliorata: in applicazioni con interfaccia grafica (GUI), il multitasking permette agli utenti di continuare a utilizzare lโapplicazione mentre altre operazioni vengono completate in background, mantenendo la reattivitร .
Condivisione delle risorse: i processi possono condividere risorse come la memoria, riducendo il consumo complessivo e ottimizzando lโuso delle risorse di sistema.
Flessibilitร : facilita lโesecuzione di diversi tipi di attivitร su un unico dispositivo, come navigare su internet mentre si ascolta musica o si scaricano file.
I principali svantaggi del multitasking sono:
Overhead del sistema: cambiare rapidamente da un processo allโaltro (ossia effettuare un cambio di contesto) richiede risorse di sistema e puรฒ rallentare le prestazioni generali.
Rischio di collisione: con piรน processi che accedono alle stesse risorse, come la memoria, puรฒ essere necessario gestire i conflitti di risorse e sincronizzare i processi, aumentando la complessitร .
Maggiore complessitร e possibilitร di errori: la gestione di piรน processi o thread richiede un controllo avanzato e puรฒ portare a errori difficili da identificare, come deadlock o race conditions.
Riduzione delle prestazioni su sistemi limitati: su sistemi con meno risorse, il multitasking puรฒ ridurre lโefficienza complessiva, creando un sovraccarico che rallenta il sistema.
Problemi di sicurezza: se i processi non sono ben isolati, un processo puรฒ influenzare o interferire con altri, creando vulnerabilitร e rischi per la sicurezza.
6 - Processo init in UNIX
In UNIX, il processo init รจ il primo processo che il kernel manda in esecuzione dopo che il computer ha terminato la fase di bootstrap ed รจ il processo padre di tutti gli altri processi del sistema. Si occupa dellโinizializzazione del sistema, della gestione degli stati di avvio e dello spegnimento del sistema e ha tipicamente PID1.
๐ซ Lezioni e slide del Prof. Aldinucci Marco del corso di Sistemi Operativi (canale B), Corso di Laurea in Informatica presso lโUniversitร di Torino, A.A. 2024-25:
๐ซ Lezioni e slide del Prof. Schifanella Claudio del corso di Laboratorio di Sistemi Operativi (canale B, turno T4), Corso di Laurea in Informatica presso lโUniversitร di Torino, A.A. 2024-25:
๐ซ Appunti di Carlos Palomino del corso di Sistemi Operativi, Corso di Laurea in Informatica presso lโUniversitร di Torino, A.A. 2024-25 (caricati sul repository GitHub del Team Studentesco Informatica):