Быстрые мьютексы и защищенные мьютексы
Начиная с Windows 2000, драйверы могут использовать быстрые мьютексы , если им требуется форма взаимного исключения с низкими затратами для кода, который выполняется в IRQL <= APC_LEVEL. Быстрый мьютекс может защитить путь кода, который должен вводиться только одним потоком за раз. Чтобы ввести путь к защищенному коду, поток получает мьютекс. Если другой поток уже получил мьютекс, выполнение текущего потока приостанавливается до освобождения мьютекса. Чтобы выйти из защищенного пути кода, поток освобождает мьютекс.
Начиная с Windows Server 2003, драйверы также могут использовать защищенные мьютексы. Защищенные мьютексы являются заменой быстрых мьютексов, но обеспечивают лучшую производительность. Как и быстрый мьютекс, защищенный мьютекс может защитить путь кода, который должен быть введен только одним потоком за раз. Однако код, использующий защищенные мьютексы, выполняется быстрее, чем код, использующий быстрые мьютексы.
В версиях Windows до Windows 8 защищенные мьютексы реализуются иначе, чем быстрые мьютексы. Путь кода, защищенный быстрым мьютексом, выполняется в IRQL = APC_LEVEL. Путь к коду, защищенный защищенным мьютексом, выполняется в IRQL <= APC_LEVEL но со всеми БПП отключены. В этих более ранних версиях Windows приобретение защищенного мьютекса выполняется быстрее, чем приобретение быстрого мьютекса. Однако эти два типа мьютексов ведут себя одинаково и распространяются на одни и те же ограничения. В частности, подпрограммы ядра, которые недопустимы для вызова в IRQL = APC_LEVEL, не должны вызываться из пути кода, защищенного либо быстрым мьютексом, либо защищенным мьютексом.
Начиная с Windows 8, защищенные мьютексы реализуются как быстрые мьютексы. В пути кода, защищенном защищенным мьютексом или быстрым мьютексом, средство проверки драйверов обрабатывает вызовы подпрограмм ядра как выполняемые в IRQL = APC_LEVEL. Как и в более ранних версиях Windows, вызовы, которые являются незаконными в APC_LEVEL, являются незаконными в пути кода, защищенном мьютексом или быстрым мьютексом.
Быстрые мьютексы
Быстрый мьютекс представлен структурой FAST_MUTEX . Драйвер выделяет собственное хранилище для структуры FAST_MUTEX , а затем вызывает подпрограмму ExInitializeFastMutex для инициализации структуры.
Поток получает быстрый мьютекс, выполнив одно из следующих действий:
Вызов подпрограммы ExAcquireFastMutex . Если мьютекс уже был приобретен другим потоком, выполнение вызывающего потока приостанавливается до тех пор, пока мьютекс не станет доступным.
Вызов подпрограммы ExTryToAcquireFastMutex для получения быстрого мьютекса без приостановки текущего потока. Подпрограмма возвращается немедленно, независимо от того, был ли приобретен мьютекс. ExTryToAcquireFastMutex возвращает значение TRUE , если он успешно получил мьютекс для вызывающего объекта; В противном случае возвращается значение FALSE.
Поток вызывает ExReleaseFastMutex для освобождения быстрого мьютекса, приобретенного ExAcquireFastMutex или ExTryToAcquireFastMutex.
Путь кода, защищенный быстрым мьютексом, выполняется в IRQL = APC_LEVEL. ExAcquireFastMutex и ExTryToAcquireFastMutex повышают текущий irQL до APC_LEVEL, а ExReleaseFastMutex восстанавливает исходный IRQL. Таким образом, все APC отключены, а поток содержит быстрый мьютекс.
Если путь кода всегда будет выполняться в APC_LEVEL, драйвер может вместо этого вызвать ExAcquireFastMutexUnsafe и ExReleaseFastMutexUnsafe , чтобы получить и освободить быстрый мьютекс. Эти подпрограммы не изменяют текущий IRQL и могут использоваться безопасно, только если текущий IRQL APC_LEVEL.
Быстрые мьютексы невозможно получить рекурсивно. Если поток, который уже содержит быстрый мьютекс, пытается получить его, этот поток будет взаимоблокироваться. Быстрые мьютексы можно использовать только в коде, который выполняется в IRQL <= APC_LEVEL.
Защищенные мьютексы
Защищенные мьютексы, доступные начиная с Windows Server 2003, выполняют ту же функцию, что и быстрые мьютексы, но с более высокой производительностью.
Начиная с Windows 8, защищенные мьютексы и быстрые мьютексы реализуются одинаково.
В версиях Windows до Windows 8 защищенные мьютексы реализуются иначе, чем быстрые мьютексы. Получение быстрого мьютекса приводит к APC_LEVEL текущего IRQL, а получение защищенного мьютекса входит в защищенную область, что является более быстрой операцией. Дополнительные сведения о защищенных регионах см. в разделах Критические регионы и Защищенные регионы.
Защищенный мьютекс представлен структурой KGUARDED_MUTEX . Драйвер выделяет собственное хранилище для структуры KGUARDED_MUTEX , а затем вызывает подпрограмму KeInitializeGuardedMutex для инициализации структуры.
Поток получает защищенный мьютекс, выполнив одно из следующих действий:
Вызов KeAcquireGuardedMutex. Если мьютекс уже был приобретен другим потоком, выполнение вызывающего потока приостанавливается до тех пор, пока мьютекс не станет доступным.
Вызов метода KeTryToAcquireGuardedMutex для получения защищенного мьютекса без приостановки текущего потока. Подпрограмма возвращается немедленно, независимо от того, был ли приобретен мьютекс. KeTryToAcquireGuardedMutex возвращает значение TRUE , если он успешно получил мьютекс для вызывающего объекта; В противном случае возвращается значение FALSE.
Поток вызывает KeReleaseGuardedMutex для освобождения защищенного мьютекса, приобретенного keAcquireGuardedMutex или KeTryToAcquireGuardedMutex.
Поток, содержащий защищенный мьютекс, неявно выполняется внутри защищенной области. KeAcquireGuardedMutex и KeTryToAcquireGuardedMutex входят в защищенную область, а KeReleaseGuardedMutex выходит из него. Все APC отключены, а поток содержит защищенный мьютекс.
Если путь кода гарантированно будет выполняться со всеми APC отключены, драйвер может вместо этого использовать KeAcquireGuardedMutexUnsafe и KeReleaseGuardedMutexUnsafe для получения и освобождения защищенного мьютекса. Эти подпрограммы не входят в защищенный регион и не выходят из нее. Их можно использовать только в уже существующем защищенном регионе или в IRQL = APC_LEVEL.
Защищенные мьютексы нельзя получить рекурсивно. Если поток, который уже содержит защищенный мьютекс, попытается получить его, этот поток будет взаимоблокирован. Защищенные мьютексы можно использовать только в коде, который выполняется в IRQL <= APC_LEVEL.