Professional Documents
Culture Documents
I Semafori
INTRODUZIONE
Nellambito della sincronizzazione di processi esistono diversi metodi adottati per garantirne
leffettivo determinismo (si definiscono tecniche di programmazione concorrente). Una soluzione
che permette di non sprecare lutilizzo della CPU (come invece accade in altri casi, come quello
delle variabili di lock) quella dei semafori, proposta da Dijkstra nel 1965 e che, con qualche
modifica, stata adottata nei vari sistemi informatici quasi universalmente. Il semaforo si rivel
infatti utile alla soluzione di diversi problemi simili, pi in generale proprio nella sincronizzazione di
processi paralleli.
Un semaforo un tipo di oggetto che impiega due operazioni per controllare le sezioni
critiche.
I semafori non sono meccanismi di intercomunicazione diretta: non consentono di scambiare dati
fra processi ma servono invece come meccanismi di sincronizzazione o di protezione per le
sezioni critiche del codice.
Un semaforo uno speciale contatore, mantenuto nel kernel, che permette, a seconda del suo
valore, di consentire o meno la prosecuzione dell'esecuzione di un programma. In questo modo
l'accesso ad una risorsa condivisa da pi processi pu essere controllato, associando ad essa un
semaforo che consente di assicurare che non pi di un processo alla volta possa usarla.
Il concetto di semaforo generale (cos come lo sono le modalit con le quali lo si utilizza), e sta
alla base della programmazione.
Un processo che deve accedere ad una risorsa eseguir un controllo del semaforo: se questo
positivo il suo valore sar decrementato, indicando che si consumato una unit della risorsa, ed il
processo potr proseguire nell'utilizzo di quest'ultima, provvedendo a rilasciarla, una volta
completate le operazioni volute, incrementando nuovamente il semaforo.
Se al momento del controllo il valore del semaforo nullo, siamo invece in una situazione in cui la
risorsa non disponibile, ed il processo si bloccher in stato di sleep fin quando chi la sta
utilizzando non la rilascer, incrementando il valore del semaforo. Non appena il semaforo torna
positivo, indicando che la risorsa disponibile, il processo sar svegliato, e si potr operare come
nel caso precedente (decremento del semaforo, accesso alla risorsa, incremento del semaforo).
Se un processo esegue una operazione di down su un semaforo che ha un valore non nullo (cio
maggiore di zero), il suo valore viene decrementato di uno e il processo continua la propria
elaborazione; se, al contrario il processo vede che un semaforo nullo viene messo in stato di
attesa (sleep) e vi rimane finch un altro processo esegue un up su quello stesso semaforo. Dal
SEMAFORI BINARI
La forma pi semplice di semaforo quella di semaforo binario (o mutex), in cui un valore diverso
da zero (solitamente 1) indica la libert di accesso, e un valore nullo l'occupazione della risorsa; in
generale per si possono usare semafori con valori interi, utilizzando il valore del contatore come
indicatore del numero di risorse ancora disponibili.
FUNZIONAMENTO DETTAGLIATO
Ogni volta che un processo/thread ha bisogno di accedere ai dati condivisi, acquisisce il mutex con
listruzione mutex_lock() (linguaggio C); quando loperazione terminata, loggetto mutex viene
rilasciato mediante il comando mutex_unlock() cos da permettere ad un altro processo/thread di
acquisirlo per eseguire le sue operazioni.
Un mutex ha due stati: bloccato e non bloccato, quando bloccato (0) da un thread, gli altri che
tentano di bloccarlo restano in attesa; quando il thread che blocca rilascia il mutex (1), uno di quelli
in attesa lo acquisisce (secondo politiche di scheduling).
SEMAFORI A CONTATORE
Sono il tipo pi classico di semafori, il cui valore pu essere impostato dal programmatore. Essi
possono essere utilizzati nei casi pi generali di sincronizzazione, un esempio il processo
produttore/consumatore.
Nei casi in cui necessario coordinare laccesso a pi istanze della stessa risorsa si rendono
quindi necessari questo tipo di semafori.
I semafori a contatore sono simili ai mutex in quanto forniscono una sincronizzazione per laccesso
alle risorse condivise, tuttavia presentano la differenza di essere inizializzati ad un valore pari al
numero di istanze della risorsa disponibili. Se le risorse non sono disponibili (valore =0), il
processo o thread rimane in attesa fino a quando una non si renda disponibile (valore >0), il
processo acquisisce quindi il semaforo (il valore viene decrementato); quando il processo/thread
ha concluso, rilascia il semaforo (incrementandone il valore), a quel punto il processo/thread in
attesa acquisisce la risorsa (se pi di uno in attesa si impiegano adeguati sistemi di scheduling).
Nello scambio di informazioni tra processi, un processo chiamato produttore (P) quando
produce e invia un messaggio (una sequenza di byte), mentre un altro processo detto
consumatore (C) quando lo riceve e lo usa. Un messaggio, in particolare, una risorsa
consumabile: una volta elaborata non esiste pi.
Il buffer dunque una risorsa condivisa tra i processi, ed gestito come una coda. Laccesso dei
produttori regolato da un semaforo il cui valore indica anche le unit di spazio disponibile nel
buffer (se, ad esempio, un vettore).
CODICE:
void invio (messaggio m) // Funzione di invio (deposito) del messaggio (come parametro) nel buffer
{
wait (spazio_disponibile); // Il processo attende lacquisizione della risorsa buffer, decrementandone il valore di spazio disponibile
wait(mutex_prod); // Il processo attende lacquisizione esclusiva del buffer per scrivervi sopra
buffer[coda]=m; // Il messaggio viene inserito nel buffer
coda=coda++; // la posizione della coda viene incrementata di 1
signal(mutex_prod); // Il processo da il segnale per la liberazione della risorsa buffer (esclusivamente)
signal (messaggio_disponibile); // Il processo da il segnale di liberazione dalla risorsa buffer incrementandone quindi il
// del numero dei messaggi disponibili
}
messaggio ricezione() // Funzione per il prelievo del messaggio dal buffer. Il valore ritornato proprio di tipo messaggio
{
messaggio m; // Si dichiara una variabile di tipo messaggio da utilizzare
wait (messaggio_disponibile); //Il processo attende lacquisizione del buffer, decrementando il numero di messaggi disponibili una volta acquisito
wait(mutex_cons); // Il processo attende lacquisizione esclusiva del buffer
m= buffer[testa]; // La variabile m acquisisce il valore del messaggio dalla [testa] del buffer
testa=testa++; // La testa viene incrementata di 1 poich ora c uno spazio in pi
signal(mutex_cons); // Il processo invia il segnale per la liberazione della risorsa buffer (esclusivamente)
signal (spazio_disponibile); // Il processo da il segnale per la liberazione del buffer, incrementando di 1 il valore dello spazio
disponibile
return m;} // La funzione ritorna il valore del messaggio precedentemente acquisito
www2.ing.unipi.it/~a008149/corsi/osor/materiale/Semafori.pdf
win.dicecca.net/public/unina/sob04/03sincronizzazionex1.pdf
users.lilik.it/~mirko/gapil/gapilsu189.html
http://www.giordanicaserta.it/frapec/sistemi/lezioni/prodcons.pdf
http://wpage.unina.it/decarl/ProdCons.pdf