Поделиться через


Обнаружение взаимоблокировки

Обнаружение взаимоблокировок отслеживает использование драйвером ресурсов, которые необходимо заблокировать— спин-блокировки, мьютексы и быстрые мьютексы. Этот параметр Driver Verifier обнаруживает логику кода, которая может вызвать взаимоблокировку в какой-то момент в будущем.

Параметр "Обнаружение взаимоблокировки" средства проверки драйверов вместе с расширением отладчика ядра !взаимоблокировки является эффективным инструментом, который позволяет избежать плохого использования этих ресурсов в коде.

Обнаружение взаимоблокировок поддерживается только в Windows XP и более поздних версиях Windows.

Причины взаимоблокировок

Взаимоблокировка возникает, когда два или более потоков вступают в конфликт над каким-либо ресурсом таким образом, что выполнение невозможно.

Наиболее распространенная форма взаимоблокировки возникает, когда два или более потоков ожидают ресурса, который принадлежит другому потоку. Это проиллюстрировано следующим образом:

Поток 1 Поток 2
Принимает блокировку A Принимает блокировку B
Блокировка запросов B Запросы блокируют A

Если обе последовательности выполняются одновременно, поток 1 никогда не получит блокировку B, так как она принадлежит потоку 2, а поток 2 никогда не получит блокировку A, так как принадлежит потоку 1. В лучшем случае это приводит к остановке участвующих потоков, а в худшем — к остановке системы.

Взаимоблокировки не ограничиваются двумя потоками и двумя ресурсами. Трехсторонняя взаимоблокировка между тремя потоками и тремя блокировками является распространенным явлением, и иногда возникают даже пяти- или шестикомпонентные взаимоблокировки. Эти взаимоблокировки требуют определенной степени "невезения", так как они полагаются на ряд вещей, происходящих одновременно. Тем не менее, чем дальше друг от друга блокировки приобретения, тем больше вероятность того, что они становятся.

Взаимоблокировки в одном потоке могут возникать, когда поток пытается принять блокировку, которая уже принадлежит ему.

Общим знаменателем всех взаимоблокировок является то, что иерархия блокировок не соблюдается. Каждый раз, когда необходимо получить несколько блокировок одновременно, каждая блокировка должна иметь четкий приоритет. Если A принимается перед B в одной точке и B перед C в другой, иерархия будет A-B-C. Это означает, что A никогда не должно быть приобретено после B или C, а B не должно быть приобретено после C.

Иерархия блокировок должна соблюдаться, даже если нет возможности возникновения взаимоблокировки, так как в процессе обслуживания кода будет легко случайно ввести взаимоблокировку.

Ресурсы, которые могут привести к взаимоблокировкам

Наиболее однозначные взаимоблокировки являются результатом принадлежащих ресурсов. К ним относятся спин-блокировки, мьютексы, быстрые мьютексы и ERESOURCEs.

Ресурсы, которые сигнализируются, а не получаются (например, события и порты LPC), как правило, вызывают гораздо более неоднозначные взаимоблокировки. Конечно, код может и слишком часто использовать эти ресурсы таким образом, чтобы два потока в конечном итоге бесконечно ждали друг друга. Однако, так как эти ресурсы фактически не принадлежат ни одному потоку, невозможно определить проступок с какой-либо степенью достоверности.

Параметр "Обнаружение взаимоблокировок" средства проверки драйверов ищет потенциальные взаимоблокировки, включающие спин-блокировки, мьютексы и быстрые мьютексы. Он не отслеживает использование ERESOURCEs, а также не отслеживает использование нехозяйственных ресурсов.

Последствия обнаружения взаимоблокировки

Процедуры обнаружения взаимоблокировок средства проверки драйверов обнаруживают нарушения иерархии блокировок, которые не обязательно являются одновременными. В большинстве случаев эти нарушения определяют пути кода, которые будут взаимоблокировкой, если будет предоставлена такая возможность.

Чтобы найти потенциальные взаимоблокировки, средство проверки драйверов создает график порядка получения ресурсов и проверяет циклы. Если создать узел для каждого ресурса и нарисовать стрелку при каждом получении одной блокировки перед другой, то циклы пути будут представлять нарушения иерархии блокировок.

Средство проверки драйверов выдает ошибку проверка при обнаружении одного из этих нарушений. Это произойдет до возникновения каких-либо фактических взаимоблокировок.

Примечание

Даже если конфликтующие пути кода никогда не могут происходить одновременно, они по-прежнему должны быть перезаписаны, если они связаны с нарушениями иерархии блокировок. Такой код является "взаимоблокировкой, ожидающей возникновения", которая может привести к реальным взаимоблокировкам, если код немного перезаписан.

Когда обнаружение взаимоблокировки обнаруживает нарушение, оно выдает проверка 0xC4 ошибок. Первый параметр этой ошибки проверка указывает на точное нарушение. Возможные нарушения:

  • Два или более потоков, участвующих в нарушении иерархии блокировки

  • Поток, который пытается получить исключительно ресурс, для которого он уже является общим владельцем (ресурсы, принадлежащие исключительно, могут быть общими; общие ресурсы не могут быть получены исключительно).

  • Поток, который пытается получить один и тот же ресурс дважды (самоблокировка).

  • Ресурс, который освобождается без предварительного приобретения.

  • Ресурс, освобожденный потоком, отличным от того, который его получил.

  • Ресурс, который инициализирован несколько раз или вообще не инициализирован;

  • Поток, который удаляется во время владения ресурсами.

  • Начиная с Windows 7 средство проверки драйверов может прогнозировать возможные взаимоблокировки. Например, при попытке использовать одну и ту же KSPIN_LOCK структуру данных как обычную спиновую блокировку, так и в качестве очереди спин-блокировки стека.

Список параметров проверка ошибок см. в разделе 0xC4 проверки ошибок (DRIVER_VERIFIER_DETECTED_VIOLATION).

Мониторинг обнаружения взаимоблокировок

Как только обнаружение взаимоблокировки обнаруживает нарушение, расширение отладчика ядра !взаимоблокировки можно использовать для точного изучения того, что произошло. Он может отображать топологию иерархии блокировок, а также стеки вызовов для каждого потока на момент первоначального получения блокировок.

Подробный пример расширения !взаимоблокировки , а также общие сведения о расширениях отладчика приведены в документации по пакету Средств отладки для Windows. Дополнительные сведения см. в разделе Отладка Windows .

Активация этого параметра

Примечание

Этот параметр несовместим с задержкой синхронизации ядра

Функцию обнаружения взаимоблокировок можно активировать для одного или нескольких драйверов с помощью диспетчера проверки драйверов или командной строки Verifier.exe. Дополнительные сведения см. в разделе Выбор параметров средства проверки драйверов.

  • В командной строке

    В командной строке параметр Обнаружение взаимоблокировки представлен битом 5 (0x20). Чтобы активировать обнаружение взаимоблокировки, используйте значение флага 0x20 или добавьте 0x20 к значению флага. Пример:

    verifier /flags 0x20 /driver MyDriver.sys
    

    Функция будет активна после следующей загрузки.

    В Windows Vista и более поздних версиях Windows можно также активировать и отключить обнаружение взаимоблокировки без перезагрузки компьютера, добавив параметр /volatile в команду . Пример:

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

    Этот параметр вступает в силу немедленно, но теряется при завершении работы или перезагрузке компьютера. Дополнительные сведения см. в разделе Использование переменных параметров.

    Функция обнаружения взаимоблокировок также включена в стандартные параметры. Пример:

    verifier /standard /driver MyDriver.sys
    
  • Использование диспетчера проверки драйверов

    1. Выберите Создать пользовательские параметры (для разработчиков кода), а затем нажмите кнопку Далее.

    2. Выберите Выбрать отдельные параметры из полного списка.

    3. Выберите (проверка) Обнаружение взаимоблокировки.

Функция обнаружения взаимоблокировок также включена в стандартные параметры. Чтобы использовать эту функцию, в диспетчере проверки драйверов выберите Создать стандартные параметры.