Иллюстрированный самоучитель по программированию систем защиты

Сериализация

Диспетчерские объекты

Спин-блокировки абсолютно необходимы в случаях, когда требуется синхронизация кода, работающего на повышенных уровнях IRQL. Но основное правило в NT – работать на повышенных уровнях IRQL в течение как можно более короткого времени значит, использование спин-блокировок следует по возможности избегать. Диспетчерские объекты NT – это набор механизмов синхронизации, рассчитанных на применение в основном для уровня IRQL PASSIVE_LEVEL.

Базой для любого диспетчерского объекта является структура DISPAT-CHER_HEADER (определена в ntddk.h). Общим свойством любого диспетчерского объекта является то, что в каждый момент времени такой объект находится в одном из двух состояний – сигнальном или несигнальном, а также то, что поток, ожидающий захвата диспетчерского объекта, блокирован и помещен в список ожидания, находящийся в структуре DISPATCHER_HEADER.

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

Единственным отличием одного диспетчерского объекта от другого является правило, в соответствии с которым меняется состояние объекта (переход в сигнальное или несигнальное состояние). В таблице 8 перечислены диспетчерские объекты и моменты изменения их состояния.

Таблица 8. Диспетчерские объекты.

Тип Объекта Переход в сигнальное состояние Результат для ожидающих потоков
Мьютекс (Mutex) Освобождение мьютекса Освобождается один из ожидающих потоков
Семафор (Semaphore) Счетчик захватов становится ненулевым Освобождается некоторое число ожидающих потоков
Событие синхронизации (Synchronization events) Установка события в сигнальное состояние Освобождается один из ожидающих потоков
Событие оповещения (Notification event) Установка события в сигнальное состояние Освобождаются все ожидающие потоки
Таймер синхронизации (Synchronization timer) Наступило время или истек интервал Освобождается один из ожидающих потоков
Таймер оповещения (Notification timer) Наступило время или истек интервал Освобождаются все ожидающие потоки
Процесс Завершился последний поток процесса Освобождаются все ожидающие потоки
Поток Поток завершился Освобождаются все ожидающие потоки
Файл Завершена операция ввода/вывода Освобождаются все ожидающие потоки

Диспетчерские объекты управляются Диспетчером объектов. Как и все объекты Диспетчера объектов, они могут иметь имена в пространстве имен Диспетчера объектов. С помощью этого имени различные драйвера и прикладные программы могут обращаться к соответствующему объекту. Кроме того, каждый процесс имеет таблицу описателей, связанных с конкретным объектом. Как уже говорилось, описатель в таблице описателей уникален и имеет смысл только в контексте конкретного процесса.

Однако Диспетчер объектов предоставляет функцию ObReferenceObjectByHandle(), которая дает возможность получения указателя на объект по его описателю. Эту функцию, как следует из вышесказанного, можно использовать только в контексте известного процесса (для которого создавался описатель), а полученный указатель на объект уже можно использовать в случайном контексте. Чтобы такой объект впоследствии мог быть удален, по окончании его использования должна быть вызвана функция ObDereference Object().

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.