- •Лекция 8. Типовые задачи синхронизации. Примитивы синхронизации в Win32 api
- •Решение
- •Задача об обедающих философах
- •Использование критической секции
- •Функции для атомарного доступа к переменным
- •Объекты ядра
- •Защита объектов ядра
- •Создание объекта ядра
- •Удаление объектов ядра
- •Совместное использование объектов ядра несколькими процессами
- •Наследование описателя объекта
- •Именованные объекты
- •Handle OpenSemaphore(dword dwDesiredAccess, bool bInheritHandle, lpstr lpszName);
- •Дублирование описателей объектов
Использование критической секции
CRITICAL_SECTION CS;
InitializeCriticalSection(&CS);
EnterCriticalSection(&CS); // Request ownership
// Access the shared resource.
LeaveCriticalSection(&CS); // Release ownership
Функции для атомарного доступа к переменным
Функции InterlockedCompareExchange, InterlockedExchangeAdd, InterlockedDecrement, InterlockedExchange, и InterlockedIncrement обеспечивают простой механизм для синхронизации доступа к общим переменным. Нити различных процессов могут использовать этот механизм, если переменная находится в общедоступной памяти.
Атомарные функции InterlockedIncrement и InterlockedDecrement объединяют два действия: увеличение (уменьшение) значения переменной и возврат результирующего значения.
LONG InterlockedIncrement(LPLONG var)
LONG InterlockedDecrement(LPLONG var)
Атомарная функция InterlockedExchange копирует значение второго параметра в первый параметр и возвращает старое значение первого параметра.
LONG InterlockedExchange( LPLONG target, LONG var);
// var -> target & old_target -> rezult
Функция InterlockedExchangeAdd увеличивает значение первого параметра на величину второго параметра и возвращает старое значение первого параметра.
LONG InterlockedExchangeAdd ( PLONG var, LONG incr);
// var += incr & old_var -> rezult
Функция InterlockedCompareExchange сравнивает первый и третий параметры и, если равны, присваивает первому параметру значение второго.
PVOID InterlockedCompareExchange(PVOID *dest, PVOID xchg, PVOID comp);
// if(dest==comp) dest <- xchg
Объекты ядра
Система позволяет создавать разнообразные объекты, доступ к которым осуществляется с помощью системных вызовов. Принадлежность объектов процессам отслеживается системой, память занятая объектами автоматически освобождается при завершении процесса. Такими объектами являются: Каналы(Pipe), Семафоры (Semaphore), Мьютексы(Mutex), Проекциифайлов,События,Нити,Процессы,Файлы, ...
Объект ядра – это структура данных, выделенная ядром ОС, содержащая информацию об объекте и доступная только ядру ОС.Некоторые элементы (имя объекта, дескриптор защиты, счетчик числа пользователей и .др. присутствуют по всех объектах, но большая их часть специфична для объектов конкретною типа. Например, у объекта «процесс» есть идентификатор процесса, базовый приоритет и код завершения.
Объекты создаются функциямиWin32API,например, CreateProcess. При создании объекта ядра, система возвращает описатель (HANDLE), идентифицирующий созданный объект. Описатель следует рассматривать как «непрозрачное» 32-битное значение, которое может быть использовано любой нитью процесса.Win32APIпредоставляет набор функций для работы с объектами ядра.
ОС Microsoftсделана так, что значения описателей являются уникальными для конкретного процесса. Поэтому, невозможно передать такое значение (с помощью какого-либо механизма межпроцессной связи) для использования другому процессу. Далее рассмотрим три механизма использования одного объекта ядра несколькими процессами.
Защита объектов ядра
С объектами ядра связан дескриптор защиты (security descriptor),который описывает, кто создал объект и кто имеет права на доступ к нему. Дескрипторы защиты обычной используют при написании серверных приложений. В клиентском приложение можно игнорировать это свойство объектов (Windows 95не поддерживает дескрипторы защиты).
Почти все функции, создающие объекты ядра, имеют аргумент - указатель на структуруsecurity_attribUtes. Большинство приложений вместо этого аргумента передают NULLи создают объект с защитой по умолчанию (такая защита подразумевает, что администратор и создатель объекта получают к нему полный доступ, а все прочие к объекту не допускаются).
typedef struct _SECURITY_ATTRIBUTES
{
DWOFD nLength; // размер структуры
LPVOID lpSecurityDescriptor; // указатель на дескриптор защиты
BOOL bIneritHandle; // флаг наследования атрибутов
} SECURITY_ATTRIBUTES;
Таблица описателей объектов ядра
При инициализации процесса система создает в нем таблицу описателей объектов ядра. Сведения о структуре этой таблицы и управлении ею не документированы, к тому же эта таблица по-разному реализуется в Windows NT, Windows 95и WindowsСЕ.
На рис. 2-1показано, как выглядит таблица описателей, принадлежащая процессу. Это просто массив структур данных. Каждая структура содержит 32-битный указатель на объект ядра, маску доступа и некоторые флаги.
Индекс Указатель на объект ядра Маска доступа ...
1 Ox???????? Ox????????
2 Ox???????? Ox????????
… … … …
Рис. 2-1. Структура таблицы описателей, принадлежащей процессу