Share via


Rilevamento di deadlock

Il rilevamento deadlock monitora l'uso delle risorse che devono essere bloccate, ovvero blocchi di spin, mutex e mutex veloci. Questa opzione Di verifica driver rileverà la logica del codice che ha il potenziale per causare un deadlock a un certo punto futuro.

L'opzione Rilevamento deadlock di Driver Verifier, insieme all'estensione del debugger del kernel !deadlock , è uno strumento efficace per assicurarsi che il codice eviti un utilizzo insufficiente di queste risorse.

Il rilevamento deadlock è supportato solo in Windows XP e nelle versioni successive di Windows.

Cause di Deadlock

Un deadlock viene causato quando due o più thread vengono in conflitto su una risorsa, in modo che nessuna esecuzione sia possibile.

La forma più comune di deadlock si verifica quando due o più thread attendeno una risorsa di proprietà dell'altro thread. Questa operazione viene illustrata come segue:

Thread 1 Thread 2
Accetta blocco A Accetta blocco B
Blocco richieste B Richieste di blocco A

Se entrambe le sequenze si verificano contemporaneamente, Thread 1 non otterrà mai Lock B perché è di proprietà di Thread 2 e Thread 2 non otterrà mai Lock A perché è di proprietà di Thread 1. Al meglio, i thread coinvolti si arrestano e, al peggio, il sistema smette di rispondere.

I deadlock non sono limitati a due thread e due risorse. I deadlock a tre vie tra tre thread e tre blocchi sono comuni, e anche cinque parti o deadlock in sei parti si verificano occasionalmente. Questi deadlock richiedono un certo grado di "cattiva fortuna" perché si basano su una serie di cose che si verificano simultaneamente. Tuttavia, più lontano sono le acquisizioni di blocchi, più probabilmente diventano.

I deadlock a thread singolo possono verificarsi quando un thread tenta di eseguire un blocco già proprietario.

Il denominatore comune tra tutti i deadlock è che la gerarchia di blocchi non è rispettata. Ogni volta che è necessario avere più blocchi acquisiti alla volta, ogni blocco deve avere una precedenza chiara. Se A viene preso prima di B a un punto e B prima di C in un altro, la gerarchia è A-B-C. Ciò significa che A non deve mai essere acquisito dopo B o C e B non deve essere acquisito dopo C.

La gerarchia di blocco deve essere seguita anche quando non esiste alcuna possibilità di deadlock, poiché nel processo di gestione del codice sarà facile introdurre accidentalmente un deadlock.

Risorse che possono causare deadlock

I deadlock più ambigui sono il risultato delle risorse di proprietà . Questi includono blocchi di spin, mutex, mutex veloci e ERESOURCEs.

Le risorse segnalate anziché acquisite (ad esempio eventi e porte LPC) tendono a causare deadlock molto più ambigui. È naturalmente possibile, e tutto troppo comune, per il codice usare queste risorse in modo tale che due thread finiranno in attesa indefinito per completare l'uno dall'altro. Tuttavia, poiché queste risorse non sono effettivamente di proprietà di un solo thread, non è possibile identificare il thread delinquente con qualsiasi grado di certezza.

L'opzione Rilevamento deadlock di Driver Verifier cerca potenziali deadlock che coinvolgono blocchi di spin, mutex e mutex veloci. Non monitora l'uso di ERESOURCEs, né monitora l'uso di risorse non gestite.

Effetti del rilevamento deadlock

Le routine di rilevamento deadlock del driver individuano le violazioni della gerarchia di blocco che non sono necessariamente simultanee. La maggior parte del tempo, queste violazioni identificano i percorsi di codice che verranno deadlock quando viene data la possibilità.

Per trovare potenziali deadlock, Driver Verifier compila un grafico dell'ordine di acquisizione delle risorse e verifica i cicli. Se si desidera creare un nodo per ogni risorsa e disegnare una freccia ogni volta che un blocco viene acquisito prima di un altro, i cicli di percorso rappresentano violazioni della gerarchia di blocchi.

Il verificatore driver emetterà un controllo di bug quando viene individuata una di queste violazioni. Ciò si verificherà prima che si verifichino deadlock effettivi.

Nota

Anche se i percorsi di codice in conflitto non possono mai verificarsi simultaneamente, devono comunque essere riscritti se comportano violazioni della gerarchia di blocchi. Questo codice è un "deadlock in attesa di verificarsi" che potrebbe causare deadlock reali se il codice viene riscritto leggermente.

Quando il rilevamento deadlock rileva una violazione, genera un controllo di bug 0xC4. Il primo parametro di questo controllo di bug indicherà la violazione esatta. Le possibili violazioni includono:

  • Due o più thread coinvolti in una violazione della gerarchia di blocchi

  • Thread che tenta di acquisire esclusivamente una risorsa per cui è già un proprietario condiviso (è possibile acquisire esclusivamente risorse di proprietà; le risorse condivise non possono essere acquisite esclusivamente).

  • Thread che tenta di acquisire la stessa risorsa due volte (un deadlock self-deadlock)

  • Risorsa rilasciata senza essere stata acquisita prima

  • Risorsa rilasciata da un thread diverso rispetto a quello acquisito

  • Risorsa inizializzata più di una volta o non inizializzata

  • Thread eliminato durante la proprietà delle risorse

  • A partire da Windows 7, Driver Verifier può prevedere possibili deadlock. Ad esempio, cercando di usare la stessa struttura di dati KSPIN_LOCK sia come blocco di rotazione regolare che come blocco spin in coda dello stack.

Per un elenco dei parametri di controllo dei bug, vedere Verifica bug 0xC4 (DRIVER_VERIFIER_DETECTED_VIOLATION ).

Monitoraggio del rilevamento deadlock

Dopo aver rilevato una violazione, l'estensione del debugger del kernel !deadlock può essere usata per analizzare esattamente ciò che si è verificato. Può visualizzare la topologia della gerarchia di blocchi e gli stack di chiamate per ogni thread al momento dell'acquisizione dei blocchi.

È disponibile un esempio dettagliato dell'estensione !deadlock , nonché informazioni generali sulle estensioni del debugger, nella documentazione di Strumenti di debug per il pacchetto Di Windows. Per informazioni dettagliate, vedere Debug di Windows .

Attivazione di questa opzione

Nota

Questa opzione non è compatibile con il ritardo di sincronizzazione del kernel

È possibile attivare la funzionalità di rilevamento deadlock per uno o più driver usando Gestione verifica driver o la riga di comando Verifier.exe. Per informazioni dettagliate, vedere Selezione delle opzioni di verifica driver.

  • Nella riga di comando

    Nella riga di comando l'opzione Rilevamento deadlock è rappresentata da Bit 5 (0x20). Per attivare Il rilevamento deadlock, usare un valore flag di 0x20 o aggiungere 0x20 al valore del flag. Ad esempio:

    verifier /flags 0x20 /driver MyDriver.sys
    

    La funzionalità sarà attiva dopo l'avvio successivo.

    In Windows Vista e versioni successive di Windows è anche possibile attivare e disattivare Il rilevamento deadlock senza riavviare il computer aggiungendo il parametro /volatile al comando. Ad esempio:

    verifier /volatile /flags 0x20 /adddriver MyDriver.sys
    

    Questa impostazione è efficace immediatamente, ma viene persa quando si arresta o si riavvia il computer. Per informazioni dettagliate, vedere Uso delle impostazioni volatili.

    La funzionalità Di rilevamento deadlock è inclusa anche nelle impostazioni standard. Ad esempio:

    verifier /standard /driver MyDriver.sys
    
  • Uso di Gestione verifica driver

    1. Selezionare Crea impostazioni personalizzate (per sviluppatori di codice) e quindi selezionare Avanti.

    2. Selezionare Seleziona singole impostazioni da un elenco completo.

    3. Selezionare (check) Rilevamento deadlock.

La funzionalità Di rilevamento deadlock è inclusa anche nelle impostazioni standard. Per usare questa funzionalità, in Gestione verifica driver selezionare Crea impostazioni standard.