Совместное использование объектов ядра несколькими процессами. Именованные объекты

Ещё один способ, позволяющий нескольким процессам совместно использовать одни и те же объекты ядра, связан с именованием этих объектов. Именование допускают многие объекты ядра. Следующие функции создают именованные объекты ядра:

HANDLE CreateMutex(

PSLCURITY_ATTRIBUTES psa,

BOOL bInitialOwner,

PCTSTR pszName);

HANDLE CreateEvent(

PSECURITY_ATTRIBUTES psa,

BOOL bManualReset,

BOOL bInitialState,

PCTSTR pszName);

HANDLE CreateSemaphore(

PSECURITY_ATTRIBUTES psa,

LONG lInitialCount,

LONG lMaximumCount,

PCTSTR pszNarne);

HANDLE CreateWaitableTimer(

PSLCURITY_ATTRIBUTES psa,

BOOL bManualReset,

PCTSTR pszName);

HANDLE CreateFileMapping(

HANDLE hFile,

PSECURITY_ATTRIBUTES psa,

DWORD flProtect,

DWORD dwMaximumSizeHigh,

DWORD dwMaximumSizeLow,

PCTSTR pszName);

HANDLE CreateJobObject(

PSECURITY_ATTRIBUTES psa,

PCTSTR pszName);

Последний параметр, pszName, у всех этих функций одинаков. Передавая в нем NULL можно создать безымянный (анонимный) объект ядра. В этом случае можно разделить объект между процессами. Чтобы разделять объект по имени, необходимо присвоить ему какое-нибудь имя. Тогда вместо NULL в параметре pszName нужно передать адрес строки с именем, завершаемой нулевым символом. Имя может быть длиной до MAX_PATH знаков (это значение определено как 260). К сожалению, Microsoft ничего не сообщает о правилах именования объектов ядра. Например, создавая объект с именем JeffObj, нет гарантии того, что в системе еще нет объекта ядра с таким именем. И что хуже, все эти объекты делят единое пространство имен. Из-за этого следующий вызов CreateSemaphore будет всегда возвращать NULL:

HANDLE hMutex = CreateMutex(NULL. FALSE, "JeffObj");

HANDLE hSem = CreateSemaphore(NULL, 1, 1, "JeffObj");

DWORD dwErrorCode = GetLastError();

После выполнения этого фрагмента значение dwErrorCode будет равно ERROR_INVALID_HANDLE.

Рассмотрим, как разделять их между процессами по именам. Допустим, после запуска процесса А вызывается функция:

HANDLE hMutexPronessA = CreateMutex(NULL,

FALSE,

"JeffMutex");

Этот вызов заставляет систему создать новый объект ядра "мъютекс" и присвоить ему имя JeffMutex. Описатель hMutexProcessA в процессе А не является наследуемым, — он и не должен быть таковым при простом именовании объектов.

Спустя какое-то время некий процесс порождает процесс В. Необязательно, чтобы последний был дочерним от процесса А; он может быть порожден Explorer или любым другим приложением. Когда процесс В приступает к работе, исполняется код:

HANDLE hMutexProcessB = CreateMutex(NULL,

FALSE,

"JeffMutex");

При этом вызове система сначала проверяет, не существует ли уже объект ядра с таким именем. Если да, то ядро проверяет тип этого объекта. Поскольку есть попытка создать мьютекс и его имя тоже JeffMutex, система проверяет права доступа вызывающего процесса к этому объекту. Если у него есть все права, в таблице описателей, принадлежащей процессу В, создается новая запись, указывающая на существующий объект ядра. Если же вызывающий процесс не имеет полных прав на доступ к объекту или если типы двух объектов с одинаковыми именами не совпадают, вызов CreateMutex заканчивается неудачно и возвращается NULL.

Однако, хотя процесс В успешно вызвал CreateMutex, новый объект-мьютекс он не создал. Вместо этого он получил свой описатель существующего объекта-мьютекса. Счетчик объекта, конечно же, увеличился на 1, и теперь этот объект не разрушится, пока его описатели не закроют оба процесса — А и В. Значения описателей объекта в обоих процессах скорее всего разные, но так и должно быть, каждый процесс будет оперировать с данным объектом ядра, используя свой описатель.

Вызывая CreateMutex, процесс В передает ей атрибуты защиты и второй параметр. Эти параметры игнорируются, если объект с указанным именем уже существует. Приложение может определить, что оно делает: создает новый объект ядра или просто открывает уже существующий, — вызвав GetLastError сразу же после вызова одной из Create-функций:

HANDLE hMutex = CreateMutex(&sa, FALSE, "JeffObj");

if (GetLastError() == ERROR_ALREADY_EXISTS)

{

// открыт описатель существующего объекта sa.lpSecurityDescriptor и второй параметр (FALSE) игнорируются

}

else

{

// создан совершенно новый объект sa.lpSecurityDescriptor и второй параметр (FALSE) используются при создании объекта

}

Есть и другой способ разделения объектов по именам. Вместо вызова Create-функции процесс может обратиться к одной из следующих Open-функций:

HANDLE OpenMutex(

DWORD dwDESIredAccess,

BOOL bInheritHandle,

PCTSTR pszName);

HANDLE OpenEvent(

DWORD dwDESIredAccess,

BOOL bInheritHandle,

PCTSTR pszName);

HANDLE OpenSemaphore(

DWORD dwDESIredAccess,

BOOL bInheritHandle,

PCTSTR pszName);

HANDLE OpenWaitableTimer(

DWORD dwDESIredAccess,

BOOL bInheritHandle,

PCTSTR pszName);

HANDLE OpenFileMapping(

DWORD dwDESIredAccess,

BOOL bInheritHandle,

PCTSTR pszName);

HANDLE OpenJobObject(

DWORD dwDESIredAccess,

BOOL bInheritHandle,

PCTSTR pszName);

Все эти функции имеют один прототип. Последний параметр, pszName, определяет имя объекта ядра. В нем нельзя передать NULL — только адрес строки с нулевым символом в конце. Эти функции просматривают единое пространство имен объектов ядра, пытаясь найти совпадение. Если объекта ядра с указанным именем нет, функции возвращают NULL, a GetLastError — код 2 (ERROR_FILE_NOT_FOUND). Но если объект ядра с заданным именем существует и если его тип идентичен тому, что указан, система проверяет, разрешен ли к данному объекту доступ запрошенного вида (через параметр dwDesiredAccess). Если такой вид доступа разрешен, таблица описателей в вызывающем процессе обновляется, и счетчик числа пользователей объекта возрастает на 1. Если параметру bInheritHandle присвоено значение TRUE, то получится наследуемый описатель.

Главное отличие между вызовом Create- и Open-функций в том, что при отсутствии указанного объекта Create-функция создает его, а Open-функция просто уведомляет об ошибке.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: