- •Операционные системы Windows32
- •Объекты ядра Windows
- •Пользователи объектов ядра
- •Защита объектов ядра
- •Дескрипторы. Таблица дескрипторов объектов ядра.
- •Создание объектов ядра
- •Закрытие объектов ядра
- •Совместное использование объектов ядра различными процессами
- •Процессы и потоки в Windows Создание процесса
- •Завершение процесса
- •Операции с процессами
- •Создание потока
- •Завершение потока
- •Потоки и библиотека языка с
- •Операции с потоками
- •Приоритеты потоков в Windows
- •Потоки в мультипроцессорных системах
- •Синхронизация потоков
- •Interlocked-функции
- •Критические секции
- •Wait-функции
- •Wait-функции для работы с одним объектом
- •Wait-функции для работы с несколькими объектами.
- •Побочные эффекты ожидания.
- •События
- •Семафоры
- •Мьютексы
- •Ожидаемые таймеры
- •Управление памятью в Windows
- •Организация виртуальной памяти Windows
- •Выделение памяти процессу
- •Атрибуты защиты страниц памяти
- •Функции менеджера памяти Windows
- •Проецируемые в память файлы
- •Проекции файлов и разделяемая память
Wait-функции
Одним из основных методов синхронизации выполнения потоков в многозадачной среде является использование специальных объектов – семафоров, событий, мьютексов и других. Такие объекты могут находиться в двух состояниях – свободном (signaled) и занятом (non-signaled). Для работы с этими объектами в Windows API имеется ряд специальных функций, которые позволяют перевести поток в состояние ожидания до тех пор, пока один или несколько объектов не перейдут в свободное состояние. Перевод потока в состояние ожидания позволяет системе не выделять на его выполнение процессорное время и таким образом снижает нагрузку на центральный процессор.
Можно выделить несколько групп Wait-функций.
Wait-функции для работы с одним объектом
Эта группа функций позволяет потоку ожидать перехода одного объекта в свободное состояние. Наиболее простой из этих функций является функция WaitForSingleObject:
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
Этой функции необходимо передать дескриптор объекта ядра, освобождения которого мы хотим ожидать и максимальное время ожидания. Функция вернет управление после того, как указанный объект перейдет в активное состояние или будет превышен интервал ожидания. До этого времени поток будет переведен в состояние ожидания, и не будет планироваться операционной системой. В случае успешного ожидания возвращается значение WAIT_OBJECT_0, в случае превышения времени ожидания – WAIT_TIMEOUT, также возможно возвращение кода ошибки WAIT_FAILED.
Время ожидания задается в миллисекундах. Если задать время ожидания равное 0 то функция только проверит состояние объекта (которое будет отражено в возвращенном значении), но не будет блокировать выполнение потока. Значение времени ожидания INFINITE позволяет ожидать освобождения объекта без ограничения времени.
Эта функция может работать со следующими объектами: Change notification, Console input, Event, Job, Mutex, Process, Semaphore, Thread, Waitable timer. Как уже было сказано выше, объекты Process и Thread переходят в свободное состояние после завершения своей работы, и соответственно ожидание на этих объектах позволяет определить, когда процесс или поток закончили работу. Логика работы других объектов будет рассмотрена в соответствующих разделах.
В Windows есть еще две функции, предназначенные для ожидания одного объекта: WaitForSingleObjectEx и SignalObjectAndWait. Первая из этих функций отличается от WaitForSingleObject тем, что позволяет работать асинхронному вызову процедур (APC) и уведомлениям о завершении ввода-вывода (I/O completition routine). Функция SignalObjectAndWait производит атомарную операцию, которая одновременно устанавливает один объект (который может быть событием, семафором или мьютексом) в свободное состояние и устанавливает режим ожидания на другом объекте.
Wait-функции для работы с несколькими объектами.
Во многих случаях бывает необходимо организовать более сложную логику ожидания, с использованием сразу нескольких объектов. Типичным представителем таких функций является функция WaitForMultipleObjects:
DWORD WaitForMultipleObjects(
DWORD nCount, // number of handles in array
CONST HANDLE *lpHandles, // object-handle array
BOOL bWaitAll, // wait option
DWORD dwMilliseconds // time-out interval
);
Этой функции передается массив дескрипторов объектов lpHandle и их число nCount. Параметр bWaitAll позволяет задать режим ожидания – если он равен истине, то условием прекращения ожидания является переход всех указанных объектов в свободное состояние. В противном случае ожидание прекращается при переходе любого объекта в активное состояние. В этом случае, определить какой именно объект вызвал реакцию функции можно с помощью возвращаемого значения: значение WAIT_OBJECT_0 соответствует первому элементу массива, далее значения увеличиваются на 1.
К этой группе функций относятся также функции WaitForMultipleObjectsEx, MsgWaitForMultipleObjects и MsgWaitForMultipleObjectsEx. Последние две функции можно использовать для обработки сообщений в процессе ожидания. Если обычная функция ожидания будет использована в потоке, который обрабатывает оконные сообщения, то обработка сообщений будет заблокирована на время ожидания (так как этот поток не планируется) и программа потеряет возможность реагировать на действия пользователя. Функции MsgWaitForMultipleObjects и MsgWaitForMultipleObjectsEx позволяют работать одновременно с очередью сообщений и ожиданием объектов.