Introduzione
Metodi per risolvere o evitare il deadlock
Deadlock prevention
Deadlock avoidance
Deadlock detection e recovery
Approccio combinato al deadlock
Introduzione ( Indice)
Il deadlock nasce quando alcuni membri di un gruppo di processi che detengono risorse sono bloccati indefinitamente nell'accesso ad altre risorse possedute da altri processi dello stesso gruppo.
ESEMPIO
Consideriamo un incrocio fra 2 strade, senza nessuna
indicazione di precedenza, a cui si presentano contemporaneamente 4 auto.
La zona centrale dell'incrocio e' divisibile in 4 settori (risorse) "desiderati"
dalle rispettive auto. Abbiamo 3 possibilita' per evitare questa situazione,
oppure per risolverla quando si verifica:
Figura 6.1
Non bisogna confondere il deadlock con la starvation. Il deadlock e' irrisolvibile quando si verifica, senza un intervento di controllo esterno. La starvation e' una situazione di stallo, da cui si potrebbe "prima o poi" uscire naturalmente. Un esempio e' una strada che si immette in un'altra, dovendo dare la precedenza. Se continuano a passare aurto, una macchina che si deve immettere non puo' farlo, per un tempo massimo non definibile a priori. Si tratta normalmente di un problema di schedulazione, ma puo' anche derivare da un errato controllo del deadlock. Ad esempio, il secondo metodo (della lista precedente) per evitare il deadlock puo' portare a starvation.
Esempi di possibili situazioni di deadlock:
Il problema e' molto sentito nei sistemi transazionali, in cui si devono garantire accessi in mutua esclusione ad un insieme di risorse (dati su cui piu' processi lavorano).
Una risorsa puo' essere:
Le risorse non sono solo oggetti fisici (CPU, stampanti ecc.) ma anche virtuali (messaggi di comunicazione, routine di sistema...).
Per definire meglio cos'e' un deadlock, consideriamo il Resourse Allocation Graph (RAG).
Figura 6.2
Le frecce indicano la necessita' di accedere ad una risorsa detenuta
da un particolare processo. In figura 6.2, il processo A possiede
la risorsa 1 e aspetta la risorsa 2, mentre il processo B possiede la risorsa
2 e aspetta la 1. Ovviamente per essere un vero deadlock occorre che le
risorse non siano ne' condivisibili ne' interrompibili. Inoltre si puo'
parlare di RAG solo se esiste una sola risorsa per ogni tipo. Nel
RAG si possono omettere i nodi risorsa.
Piu' formalmente abbiamo le seguenti quattro
Condizioni di Coffman, Elphick e Shoshani (1971) per l'esistenza di deadlock:
Nota 1
I processi individuati con le precedenti condizioni possono non essere
tutti e soli quelli effettivamente bloccati nel deadlock.
Figura 6.3
Anche il processo C e' bloccato, ma se si impedisce il ciclo, si libera anche C.
Nota 2
Se di una risorsa esistono piu' istanze indifferenti, l'esistenza di un
ciclo non e' piu' sufficiente per l'esistenza del deadlock. In questo caso,
in effetti, occorre considerare una tabella anziche' un grafo.
Nota 3
In alcune transazioni ci possono essere richieste del tipo:
Modello di richieste AND/OR

Figura 6.4
Se il processo A desidera una risorsa posseduta da D oppure una risorsa posseduta da B, c'e' deadlock solo se A e' un knot. Un vertice V e' un knot se per qualunque nodo W, l'asserzione "W e' raggiungibile da V implica che V e' raggiungibile da W" e' vera.
Nota 3
Si parte sempre da una condizione supposta vera: prima o poi ogni processo
rilascia tutte le risorse che possiede. Cioe' non si considerano ad esempio
eventuali errori di programmazione per cui un programma va in loop e non
termina mai.
Metodi per risolvere o evitare il deadlock ( Indice)
Ci sono 3 approcci fondamentali, 2 per prevenire il deadlock, 1 per rilevarlo (e quindi romperlo) dopo che si e' verificato.
Prevention. Nell'esempio iniziale corrisponde al primo caso (semaforo). Ha gli stessi pregi e difetti del semaforo:
Si puo' anche evitare queste tecniche e ricorrere semplicemente all'uso di un time-out. Ogni processo puo' detenere un insieme di risorse solo per un certo tempo massimo, altrimente viene interrotto e le risorse recuperate (vedi deadlock recovery ). E' un metodo poco dispendioso ma molto "doloroso" se il tempo limite non e' calcolato correttamente.
1. Deadlock prevention (Indice)
Le prime proposte vengono da Havender (69) e si ottengono negando una alla volta le 4 ipotesi per l'esistenza del deadlock. In realta' se ne considerano solo 3, visto che non si puo' negare che ci siano risorse strettamente dedicate e non suddivise.
2. Deadlock Avoidance
(Indice)
Con il deadlock prevention si utilizzano poco le
risorse. Conoscendo meglio le caratteristiche delle richieste, si potrebbero
utilizzare meglio. Occorre considerare lo stato del sistema, formato
da:
Dichiarazione delle future richieste
Ogni processo dichiara preventivamente (anche per
singola transazione) quale e' il massimo numero di risorse di cui avra'
eventualmente bisogno per ogni tipo. Un algoritmo controlla che lo stato
di esecuzione complessivo, man mano che si assegnano successivamente le
risorse, non porti mai a deadlock.
Uno stato e' detto safe se il sistema
puo' allocare tutte le risorse che i processi possono ancora chiedere per
terminare la loro transazione (in un qualche preciso ordine) evitando il
deadlock, ossia se esiste un modo per terminare tutte le transazioni attive.
Le possibili sequenze di assegnazione di risorse ai processi che portano
alla terminazione sono dette safe sequence.
In uno stato S, una sequnza di processi P
= <p1, p2, p3, ...., pn> e' detta safe se: per
qualunque pi, le richieste che pi puo' ancora fare possono
essere soddisfatte considerando le risorse disponibili e quelle possedute
dai processi pj con j<i nello stato S.
In pratica, in uno stato safe S, il processo
p1 puo' terminare utilizzando le risorse disponibili, quindi rilascia
tutte le sue risorse. Il processo p2 puo' allora terminare usando
le risorse disponibili in S piu' quelle gia' possedute (e rilasciate)
da p1 e cosi' via. Possono esistere piu' safe sequence.
Lo stato iniziale (nessuna transazione attiva) e'
safe. Muovendosi solo su stati safe (cioe' accettando di attribuire risorse
solo se lo stato risultante e' ancora safe, sospendendo in attesa il processo
richiedente altrimenti) non si va mai in uno stato di deadlock. Uno stato
unsafe non evolve necessariamente in uno di deadlock, poiche'
le richieste dichiarate di risorse sono massimali (potrebbero non essere
effettivamente richieste tutte), ma non si puo' sapere a priori.
Il S.O. deve quindi deve evitare di entrare in uno
stato unsafe.
Esempio
Supponiamo di avere 12 disk driver. Al tempo T0
rappresentato sotto, il sistema e' safe perche' esiste la sequenza safe
<p1, p0, p2>.
processi massima
risorse
richiesta allocate
p0 . . . . . 10 . . . . . . . . 5
p1 . . . . . 4 . . . . . . . . 2
p2 . . . . . 9 . . . . . . . . 2
Se pero', successivamente, p2 richiede
1 nuovo disco, e gli viene allocato, il sistema non e' piu' safe perche'
p1 puo' terminare ma poi p0 e p2 rimangono bloccati.
L'algoritmo che consente di capire se uno stato e
safe oppure no si chiama
Algoritmo del Banchiere
Struttura dati:
n
numero di processi del sistema
m
numero di tipi di risorse
available [m] istanze disponibili di ogni risorsa
max[n,m] massima richiesta
per ogni processo
allocation[n,m] risorse allocate per processo
need[n,m] risorse ancora richiedibili
need[i,j]=max[i,j]-allocation[i.j]
req[n,m] richieste considerate
in un certo istante
req[i,j]+allocation[i.j]<=max[i.j]
req(i) array
i-esimo (richieste di pi
Quando un processo pi effettua una richiesta req(i), l'algoritmo effettua i controlli:
Il nuovo stato sarebbe:
available = available - req
allocation (i)= allocation(i) + req(i)
need(i) = need(i) - req(i)
Se il nuovo stato e' safe, la richiesta e' soddisfatta, altrimenti
il processo attende.
Sviluppo del punto 3
Si puo' dimostrare che l'ordine con cui sono trovati i valori di
i che soddisfano il punto 2 non incide sull'esistenza di almeno una
di tale sequenza (se ne esiste almeno una, la si trova).
Nota:
I processi sospesi devranno essere riconsiderati successivamente (pericolo
di starvation).
ESEMPIO
n = 5 {p1, p2, p3, p4, p5} processi
m = 3 {A, B, C} tale che |A| = 10 istanze
|B| = 5
|C| = 7
al tempo T0 lo stato e'
allocation max
available
A B C
A B C A B C
3 3 2
p0 0 1 0 7 5
3
p1 2 0 0 3 2
2
p2 3 0 2 9 0
2
p3 2 1 1 2 2
2
p4 0 0 2 4 3
3
E' in uno stato safe.
safe sequence: <p1, p3, p4, p2, p0>
Sia req(1) = (1, 0, 2) la richiesta di p1 all'istante T1.
Se accettata il nuovo stato sarebbe:
allocation need
available
A B C
A B C A B C
2 3 0
p0 0 1 0 7 4
3
p1 3 0 2
0 2 0
p2 3 0 2 6 0
0
p3 2 1 1 0 1
1
p4 0 0 2 4 3
1
E' ancora safe. Le possibili sequenze sono:
<p1, p3, p4, p2, p0> e <p1, p4, p3, p0, p2>
Invece la richiesta req(4) = (3, 3,0) porterebbe ad uno stato unsafe.
3. Deadlock Detection e Recovery
( Indice)
Il sistema puo' lasciare avvenire un deadlock, controllando
periodicamante l'allocazione. Se e' avvenuto un deadlock si effettua un
recovery.
Supponiamo di avere anche piu' istanze per ogni tipo di risorsa. La struttura da usare e' simile a quella dell'algoritmo del banchiere, senza le caratteristiche relative alle richieste.
n
numero di processi del sistema
m
numero di tipi di risorse
available [m] istanze disponibili di ogni risorsa
allocation[n,m] risorse allocate per processo
req[n,m] richieste non ancora
soddisfatte
Si controlla se c'e' una sequenza possibile di terminazione, supposto che nessun processo faccia altre richieste. Se non esiste una sequenza, c'e' un deadlock.
Algoritmo deadlock detection
ESEMPIO
5 processi e 3 tipi di risorse {A, B, C} con |A|=7, |B|=2, |C|=6.
allocation
request available
A B C
A B C A B
C
p0 0 1 0
0 0 0 0 0
1
p1 2 0 0
2 0 2
p2 3 0 2
0 0 0
p3 2 1 1
1 0 0
p4 0 0 2
0 0 2
Il sistema non e' in deadlock. Se invece le richieste di p2 fossero
<0, 0, 2>, si avrebbe un deadlock per p1, p2, p3 e
p4.
In pratica, si fa una supposizione ottimistica, cioe' che dopo aver avuto
le risorse desiderate le altre risorse verranno rilasciate. Se cio' non
accade, o qualche processo fa altre richieste, potrebbe capitare successivamente
un deadlock, che sara' scoperto nell'analisi successiva.
Attivazione algoritmo di deadlock detection
L'algoritmo e' attivabile seguendo vari criteri:
Recovery dal deadlock
Due possibilita':
Nota: quando una risorsa viene "tolta" ad un processo, puo' rimanere in uno stato intermedio non corretto. Ad esempio se un processo stava scrivendo su un file, ma non ha ancora completato la scrittura, possono rimanere delle incongruenze. Se si stava stampando un file, occorre resettare la printer ecc.
1. Uccisione di processi
I processi uccisi sono interrotti, le risorse che possedeva sono liberate
(possibilita' di stati incorretti) e fatti successivamente ripartire (devono
quindi rioccupare le risorse liberate prima). Si possono usare 2 metodi:
Nel secondo caso si puo' cercare di uccidere il processo che comporta la perdita minore e la massima "resa" per la risoluzione del deadlock. Non e' facile perche' vanno considerati diversi fattori:
2. Interruzione delle risorse
Ci sono 3 passi da compiere:
Rollback
Per effettuare il roll back di un processo ad uno stato di calcolo precedente
(non all'istante iniziale) e' necessario effettuare un checkpoint, cioe'
memorizzarne uno stato intermedio completo.
Il problema e' analogo per quanto riguarda una risorsa: quando una risorsa
e' interrotta, ed attribuita ad un altro processo, deve essere riportato
ad uno stato corretto (reset della printer, cancellazione di quanto scritto
precedente in un file ecc.)
Di questo argomento si parlera' piu' in dettaglio nella sezione relativa
alle transazioni distribuite.
Approccio combinato al deadlock ( Indice)
Sono possibili anche approcci combinati. Ad esempio le risorse possono essere partizionate in classi ordinate gerarchicamente, e puo' essere utilizzato un metodo diverso akk'interno di ogni classe. Una possibile suddivisione:
Sommario
| Principio e politica | Vantaggi | Svantaggi |
| Detection
Allocazione libera: le risorse sono garantite appena possibile |
Nessun ritardo nell'inizializzazione dei processi Facilita l'intervento on line | Perdita della possibilita' di sfruttare la preemption possibile con certe risorse. |
| Prevention
Conservativa, scarso sfruttamento delle risorse |
Richiesta unica delle risorse
Lavora bene con processi che effettuano una singola fase di attivita', non e' necessaria preemption. Preemption Conveniente se lo stato delle risorse puo' essere salvato o non ha memoria Ordinamento risorse Puo' utilizzare controlli compile time I problemi sono risolti "fuori" dal programma. |
Richiesta unica delle risorse
Inefficiente Ritarda l'inizio dei processi Preemption Interrompe meno di quanto necessario Soggetta a restart ciclico Ordinamento risorse Non consente la richiesta incrementale delle risorse. |
| Avoidance | Non e' necessaria preemption | Devono essere note le massime richieste future
I Processi possono essere bloccati anche a lungo. |