- •Глава 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).
- •Анонимный канал
- •Создание анонимных каналов
- •Соединение клиентов с анонимным каналом
- •Обмен данными по анонимному каналу
- •Именованный канал
- •Функция создания именованного канала
- •Функция соединения сервера с клиентом
- •Отключение сервера от клиента
- •Функция ожидания операции именованного канала
- •Функция объединения функций именованного канала
- •Подключение клиента к серверу
If (!ReleaseSemaphore( ghSemaphore, 1, null)) /// Если ошибка
printf("ReleaseSemaphore ошибка: %d\n", GetLastError());
break;
/// Семафор не был сигнализирован, поэтому произошел тайм-аут.
case WAIT_TIMEOUT: /// Время ожидания истекло
printf("Поток %d: время ожидания истекло\n", GetCurrentThreadId());
break;
}
}
return TRUE;
}
§4. Синхронизация задач с помощью объектов ядра «мьютекс» (Mutex).
Мьютекс — аналог одноместного семафора, нужен для синхронизации одновременно выполняющихся потоков. Мьютекс отличается от семафора тем, что только владеющий им поток может его освободить, т. е. перевести в отмеченное состояние.
Мьютекс содержит счетчик числа пользователей, счетчик рекурсий и идентификатор потока-владельца.
Идентификатор потока определяет, какой поток захватил мьютекс. Счетчик рекурсий определяет, сколько раз он это сделал.
Если идентификатор потока равен 0, то мьютекс находится в сигнальном состоянии и не захвачен ни одним потоком. Если идентификатор потока не равен 0, то мьютекс захвачен одним потоком и находится в несигнальном состоянии.
Эти объекты весьма похожи на критические секции — за исключением того, что с их помощью можно синхронизировать доступ к данным со стороны нескольких процессов.
Функция создания мьютекса
HANDLE CreateMutex(
IN LPSECURITY_ATTRIBUTES lpMutexAttr,
IN BOOL bInitialOwner,
IN LPCSTR lpName
);
Краткое описание.
Первый вызов функции приводит к созданию объекта ядра «мьютекс», остальные вызовы просто возвращают соответствующим потокам описатели этого объекта, значения которых специфичны для каждого процесса.
Параметры и описание:
(1) lpMutexAttr определяет указатель на структуру SECURITY_ATTRIBUTES. Если этот параметр равен NULL, дескриптор не может наследоваться дочерними процессами. Член этой структуры lpSecurityDescriptor определяет дескриптор безопасности для нового мьютекса. Если lpMutexAttr имеет значение NULL, мьютекс получает дескриптор безопасности по умолчанию.
(2) bInitialOwner определяет начальное состояние мьютекса. TRUE — несигнальное состояние (идентификатор потока-владельца в мьютексе приравнивается идентификатору вызывающего потока; счетчик рекурсии равен единице; идентификатор потока равен идентификатору вызвавшего потока). FALSE — сигнальное состояние (мьютекс не принадлежит ни одному из потоков, находится в свободном состоянии; счетчик рекурсии равен нулю; идентификатор потока равен нулю).
(3) lpName определяет имя мьютекса.
Возвращаемое значение:
Если функция завершается успешно, возвращаемое значение является дескриптором созданного объекта мьютекса, иначе возвращаемое значение равно NULL.
Если мьютекс является именованным мьютексом и объект существовал до этого вызова функции, возвращаемое значение является дескриптором существующего объекта, GetLastError возвращает ERROR_ALREADY_EXISTS, bInitialOwner игнорируется, и вызывающему потоку не предоставляется право собственности. Однако, если у вызывающей стороны есть ограниченные права доступа, функция завершится с ошибкой ERROR_ACCESS_DENIED, и вызывающая сторона должна использовать функцию OpenMutex.