Você está na página 1de 4

TPSIT 17/10/2016

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.

DEFINIZIONE DEL CONCETTO DI SEMAFORO

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).

In dettaglio, un tentativo di entrare nella sezione critica rappresentabile da unoperazione


atomica di tipo request (in seguito down), mentre unuscita da essa indicata da una release (in
seguito up). Loperazione di up incrementa di uno il valore del semaforo, quella di down lo
decrementa della stessa quantit.

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

Andrea Altomare Semafori binari, a contatore e processo Produttore/Consumatore 1


TPSIT 17/10/2016
momento che la sincronizzazione tramite semafori di fatto un tipo di comunicazione tra processi
per mezzo di variabili condivise, importantissimo che ogni operazione di accesso a tali variabili (e
quindi sia il test su di esse che la loro modifica) costituisca un'unica azione atomica, cio una
sequenza di istruzioni non interrompibile: se un processo accede o modifica il valore di un certo
semaforo, il sistema operativo impedisce (solitamente con una semplice disabilitazione degli
interrupt) ad ogni altro processo di fare altrettanto, finch questo non abbia finito e concluso le sue
operazioni (compresa anche quella eventuale di ingresso nello stato di sleep), pena l'insuccesso
della sincronizzazione.

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

Un mutex (mutual exclusion) un oggetto che permette a processi o thread concorrenti di


sincronizzare laccesso a dati condivisi.

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).

Andrea Altomare Semafori binari, a contatore e processo Produttore/Consumatore 2


TPSIT 17/10/2016
SEMAFORI APPLICATI AL PROCESSO PRODUTTORE/CONSUMATORE

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 produttore deposita un messaggio in unarea di memoria e il consumatore lo preleva dalla stessa


area. La determinazione delle regole di sincronizzazione prevede che il produttore non possa
inserire un nuovo messaggio se il buffer pieno, e il consumatore prelevi un messaggio solo se il
buffer non vuoto.

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).

Laccesso dei consumatori analogamente regolato da un semaforo che indica il messaggio


disponibile.

CODICE:

semaforo messaggio_disponibile=0; // Rappresenta il numero di messaggi disponibili per lelaborazione


semaforo spazio_disponibile = N; // Rappresenta gli N spazi disponibili nel buffer
semaforo mutex_prod=1; // Rappresenta lo stato del semaforo binario che indica la disponibilit del buffer ai produttori
semaforo mutex_cons=1; // Rappresenta lo stato del semaforo binario che indica la disponibilit del buffer ai consumatori
messaggio buffer[N]; // Buffer utilizzato per depositare/prelevare i messaggi
int testa, coda; // Indicano le posizioni di testa e di coda per prelevare o depositare i messaggi

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

Andrea Altomare Semafori binari, a contatore e processo Produttore/Consumatore 3


TPSIT 17/10/2016
FONTI

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

Andrea Altomare Semafori binari, a contatore e processo Produttore/Consumatore 4