
- •Лекция 8. Типовые задачи синхронизации. Примитивы синхронизации в Win32 api
- •Решение
- •Задача об обедающих философах
- •Использование критической секции
- •Функции для атомарного доступа к переменным
- •Объекты ядра
- •Защита объектов ядра
- •Создание объекта ядра
- •Удаление объектов ядра
- •Совместное использование объектов ядра несколькими процессами
- •Наследование описателя объекта
- •Именованные объекты
- •Handle OpenSemaphore(dword dwDesiredAccess, bool bInheritHandle, lpstr lpszName);
- •Дублирование описателей объектов
Создание объекта ядра
Когда процесс инициализируется таблица описателей пуста. Но стоит одному из его потоков вызвать функцию, создающую объект ядра (например, CreateFileMapping),как ядро выделяет для этого объекта блок памяти и инициализирует его: далее; ядро просматривает таблицу описателей, принадлежащую данному процессу, и отыскивает свободную запись. В указатель записывается адрес структуры данных объекта ядра (в области ОС), маска доступа —на доступ без ограничений, и, наконец, определяется последний компонент —флаги.
Значение возвращаемого описателя представляет собой индекс в таблице объектов, принадлежащей процессу, и таким образом идентифицирует место, где хранится информация, связанная с объектом ядра. Значение описателей не документировано и может быть изменено, оно может быть индексом или смещением в таблице, может комбинироватся с идентификаторм процесса и т.п.
Если вызов функции, создающей объект ядра, неудачен, то обычно возвращается О(NULL).Такая ситуация возможна только при острой нехватке памяти или при наличии проблем с защитой. К сожалению, отдельные функции возвращают в таких случаях не 0,а-1 (INVALID_HANDLE_VAULE).Например, если CreateFileне сможет открыть указанный файл, она вернет именно INVALID_HANDLE_VALUE.Так что следует быть осторожны при проверке значения, возвращаемого функцией.
Удаление объектов ядра
Объекты ядра принадлежат ядру, а не процессу Важно учитывать, что при завершении процесса объект ядра может бытьне разрушен.В большинстве случаев такой объект все же разрушается; но если созданный объект используется другим процессом, ядро запретит разрушение объекта до тех пор, пока от него не откажется и тот, другой процесс.
Ядру известно, сколько процессов использует конкретный объект ядра, поскольку в каждом объекте есть счетчик числа его пользователей. В момент создания объекта счетчику присваивается единица. Когда к существующему объекту ядра обращается другой процесс, счетчик увеличивается на единицу. А когда процесс завершается, счетчики всех, еще используемых им объектом ядра автоматически уменьшаются на единицу. Как только счетчик какого-либо объекта обнуляется, ядро уничтожает этот объект.
По окончанию работы с объектом ядра его нужно закрыть вызовом CloseHandle.
Эта функция сначала проверяет таблицу описателей, принадлежащую процессу, чтобы убедиться, идентифицирует ли переданный ей описатель объект, к которому этот процесс действительно имеет доступ. Если переданный описатель неверен, функция возвращает FALSE, a GetLastError—код ERROR_INVALID_HANDLE.Если же индекс достоверен, система получает адрес объекта ядра и уменьшает счетчик числа пользователей; если счетчик станет равным нулю, ядро удалит объект из памяти.
CloseHandleудаляет соответствующую запись об объекте из таблицы описателей. При этом запись удаляется независимо от того, разрушен объект ядра или нет! После вызова CloseHandleпроцесс больше не имеет доступа к объекту, но, если счетчик не обнулен, объект остается в памяти. Это значит лишь, что объект используется другим процессом. Когда остальные процессы завершат свою работу с этим объектом (вызвав CloseHandle),он будет разрушен.
По завершении процесса операционная система освобождает все ресурсы, принадлежавшие этому процессу.