Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
196
Добавлен:
20.02.2016
Размер:
115.2 Кб
Скачать

[11.2.1] Ожидание (захват) диспетчерских объектов

Как уже было сказано, каждый диспетчерский объект всегда находится в одном из двух состояний – сигнальном (свободном) или несигнальном (занятым). Термины “свободный” и “занятый” довольно вольные, поэтому лучше использовать термины сигнальный и несигнальный. Для ожидания момента перехода объекта из несигнального в сигнальное состояние служат специальные функции ожидания: KeWaitForSingleObject() и KeWaitForMultipleObjects(). Важной особенностью этих функций служит то, что в качестве одного из их параметров указывается интервал времени, в течение которого необходимо ждать.

Если указан нулевой интервал времени (но не NULL !!!), вызов функции ожидания не блокирует поток. В этом случае она работает как функция проверки состояния диспетчерского объекта и может быть вызвана на уровне IRQL<=DISPATCH_LEVEL.

Если интервал времени не указан (NULL в качестве параметра), или указан ненулевой интервал времени, функции ожидания можно вызывать на уровне IRQL строго<DISPATCH_LEVEL. В противном случае будет сделана попытка блокирования потока, но, как мы говорили раньше, механизм диспетчеризации на уровнях IRQL >= DISPATCH_LEVEL не работает. Переключение контекста потока не сможет произойти, и функция ожидания завершит работу, как будто ожидаемый диспетчерский объект находится в сигнальном состоянии.

Отличие функции KeWaitForMultipleObjects() от KeWaitForSingleObject() в том, что она может ожидать перехода в сигнальное состояние сразу всех указанных в ней диспетчерских объектов, либо любого одного из них.

[11.2.2] Мьютексы ядра

Слово Мьютекс (mutex = Mutually EXclusive) означает взаимоисключение, т.е. мьютекс обеспечивает нескольким потокам взаимоисключающий доступ к совместно используемому ресурсу.

Вначале отметим , что кроме мьютексов ядра, есть еще быстрые мьютексы, являющиеся объектами исполнительной системы и не являющиеся диспетчерскими объектами. Мьютексы ядра обычно называют просто мьютексами.

Мьютексы ядра – это диспетчерские объекты – эквиваленты спин-блокировок. Двумя важными отличиями мьютексов от спин-блокировок являются:

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

  2. Для мьютексов предусмотрен механизм исключения взаимоблокировок (см. п. [11.1.1.2]). Он заключается в том, что при инициализации мьютекса функцией KeInitializeMutex() указывается уровень (level) мьютекса. Если потоку требуется захватить несколько мьютексов одновременно, он должен делать это в порядке возрастания значения level.

Функции работы с мьютексами ядра

VOID KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level);

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

LONG KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait);

Освобождение мьютекса, с указанием того, последует ли сразу после этого вызов функции ожидания мьютекса. Если параметр Wait равен TRUE, сразу за вызовом KeReleaseMutex() должен следовать вызов одной из функций ожидания KeWaitXxx() (см. п. [11.2.1]). В этом случае гарантируется, что пара функций – освобождение мьютекса и ожидание – будет выполнена как одна операция, без возможного в противном случае переключения контекста потока. Возвращаемым значением будет 0, если мьютекс был освобожден, т.е. переведен из несигнального состояния в сигнальное. В противном случае возвращается ненулевое значение.

LONG KeReadStateMutex(IN PKMUTEX Mutex);

Возвращает состояние мьютекса – сигнальное или несигнальное.

Соседние файлы в папке Лабы по драйверам