- •Глава 2. Синхронизация задач с использованием api-функций и механизмов ядра.
- •§0. Объекты ядра. Основы.
- •Учет пользователей объектов ядра
- •Процесс и поток: краткая характеристика
- •Создание объекта ядра
- •Закрытие объекта ядра
- •Синхронизация объектов
- •Наследование описателей объекта
- •Именованные объекты
- •3. После этого вызова система проверяет, существует ли уже объект ядра с таким же именем. Если существует, то
- •Open-функции
- •Дублирование описателей объектов
- •1) Процесс-катализатор.
- •2) Процесс-источник.
- •3) Процесс-приемник.
- •Исходное состояние
- •1 0XF0000000 (неприм.) (неприм.)
- •1 0XF0000000 (неприм.) (неприм.)
- •Состояние после вызова DuplicateHandle
- •§1. Синхронизация задач с использованием функций ожидания.
- •Функция ожидания одного объекта
- •Функция ожидания нескольких объектов
- •Функция ожидания нескольких объектов и сообщений
- •Функция создания дочернего процесса
- •Функция завершения дочернего процесса из самого дочернего процесса
- •Функция завершения дочернего процесса из процесса родителя
- •Функция создания вторичного потока
- •Функция завершения дочернего потока из самого дочернего потока (only c)
- •Функция завершения дочернего потока из потока родителя
- •If (my_file.Is_open()) { /// Если удалось открыть
- •Функция создания вторичного потока _beginthread
- •Функция создания вторичного потока _beginthreadex
- •§2. Синхронизация задач с помощью объектов ядра «событие» (Event).
- •Функция создания события
- •Функция установки сигнального состояния события
- •Функция установки несигнального состояния события
- •Функция открытия существующего именованного объекта события
- •Дескриптор защиты (структура)
- •§3. Синхронизация задач с помощью объектов ядра «семафор» (Semaphore).
- •Функция создания семафора
- •Функция открытия семафора
- •Функция увеличения счетчика семафора на указанное количество
- •If (!ReleaseSemaphore( ghSemaphore, 1, null)) /// Если ошибка
- •§4. Синхронизация задач с помощью объектов ядра «мьютекс» (Mutex).
- •Функция создания мьютекса
- •Функция открытия существующего именованного объекта мьютекса
- •Функция освобождения владельца указанного объекта мьютекса
- •§5. Синхронизация задач с помощью объектов ядра «уведомление об изменении» (Change Notification).
- •Функция создания объекта ядра «уведомление об изменении»
- •Функция перезапуска объекта ядра «уведомление об изменении»
- •Функция остановки мониторинга дескриптора объекта ядра «уведомление об изменении»
- •§6. Синхронизация задач с помощью объектов ядра «таймер ожидания» (Waitable Timer).
- •Функция создания объекта ядра «таймер ожидания»
- •Функция активации объекта ядра «ожидаемый таймер»
- •Функция открытия объекта ядра «ожидаемый таймер»
- •1. Функцией CancelWaitableTimer().
- •2. Функцией SetWaitableTimer().
- •If (bSuccess) /// Если успешно, то
- •If (bSuccess) /// Если успешно, то
- •§7. Синхронизация задач с помощью объектов ядра «канал» (Pipe).
- •Анонимный канал
- •Создание анонимных каналов
- •Соединение клиентов с анонимным каналом
- •Обмен данными по анонимному каналу
- •Именованный канал
- •Функция создания именованного канала
- •Функция соединения сервера с клиентом
- •Отключение сервера от клиента
- •Функция ожидания операции именованного канала
- •Функция объединения функций именованного канала
- •Подключение клиента к серверу
Функция открытия существующего именованного объекта события
HANDLE OpenEvent(
IN DWORD dwDesiredAccess,
IN BOOL bInheritHandle,
IN LPCSTR lpName
);
Краткое описание:
Функция OpenEvent позволяет нескольким процессам открывать дескрипторы одного и того же объекта события. Функция завершается успешно, только если какой-то процесс уже создал событие с помощью функции CreateEvent.
Параметры и описание:
(1) dwDesiredAccess — определяет доступ потока к объекту. 3 основных варианта: EVENT_ALL_ACCESS (можно выполнять все действия по отношению к объекту события), EVENT_MODIFY_STATE (можно использовать только функции SetEvent, ResetEvent и PulseEvent), SYNCHRONIZE (можно использовать события функций ожидания).
(2) bInheritHandle — определяет наследование. TRUE — дочерние процессы наследуют дескриптор. FALSE — не наследуют.
(3) lpName — определяет имя события.
Возвращаемое значение.
Если функция завершилась успешно, она возвращает дескриптор объекта события, в противном случае — возвращает NULL.
Пример.
Поток 1 готовит данные для обработки вторичными потоками 2 и 3.
Поток 1
HANDLE E[2];
E[0] = CreateEvent(NULL, true, false, "MyEvent2");
E[1] = CreateEvent(NULL, true, false, "MyEvent3");
HANDLE H = CreateEvent(NULL, true, false, "MyEvent1");
// подготовка данных…
// считывание из файла…
// далее установка события MyEvent1:
SetEvent(H);
// ожидание событий MyEvent2 и MyEvent3
WaitForMultipleObjects(2, E, true, INFINITE);
ResetEvent(E[0]);
ResetEvent(E[1]);
ResetEvent(H);
// продолжение выполнения после остановки события
С помощью MyEvent1 поток 1 будет оповещать потоки 2 и 3 об окончании подготовки данных. События MyEvent2 и MyEvent3 будут использоваться для получения информации от потоков 2 и 3.
После завершения подготовки данных событие MyEvent1 переводится в сигнальное состояние, которое распознается потоками 2 и 3.
Затем вызывается функция WaitForMultipleObjects, обеспечивающая ожидание до тех пор, пока события MyEvent2 и MyEvent3 не окажутся в сигнальном состоянии. После этого работа потока 1 будет продолжена.
Перед продолжением работы необходимо сбросить все события в несигнальное состояние функцией ResetEvent. Такой сброс необходим, если приведенный код выполняется больше одного раза.
Поскольку окончание ожидания наступает при сигнальном состоянии событий MyEvent2 и MyEvent3, то оно сохранится без вызовов функции ResetEvent. При повторном обращении к функции WaitForMultipleObjects ожидание не состоится.
В потоке 2, который должен среагировать на событие MyEvent1, нужно выполнить операции над подготовленными данными и оповестить поток 1 о завершении своего выполнения через событие MyEvent2.
Поток 2
HANDLE H = CreateEvent(NULL, true, false, "MyEvent1");
WaitForSingleObject(H, INFINITE);
// начало обработки данных, подготовленных потоком 1.
// …
// сообщение об окончании обработки:
SetEvent(OpenEvent(EVENT_ALL_ACCESS,true,"MyEvent2"));
Код начинается с создания (открытия) дескриптора события MyEvent1 и ожидания того, когда это событие будет переведено первым потоком в сигнальное состояние.
После того, как это произойдет, начнется обработка полученных данных.
После этого функция OpenEvent откроет дескриптор события. Функция SetEvent переведет событие в сигнальное состояние.
В потоке 3 необходимо разместить аналогичный код, заменив событие MyEvent2 на MyEvent3.
Домашнее задание.
Узнать про дескриптор защиты.