Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






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






Как уже отмечалось, объекты ядра могут использоваться различными процессами. Более того, большая их часть прямо предназначена для того, чтобы организовывать взаимосвязь между процессами (или потоками). Для того чтобы два процесса могли использовать один объект, необходимо чтобы у них в таблицах дескрипторов имелись записи, которые ссылаются на этот объект. Достигнуть этого можно тремя способами:

· передать объект по наследству от родителя потомку;

· копировать объект между процессами;

· использовать имена объектов.

Рассмотрим эти способы.

При создании объекта мы можем указать значение флага bInheritHandle, которое определяет, будет ли дескриптор этого объекта передан его дочерним процессам. При создании дочернего процесса Windows просматривает таблицу дескрипторов родительского процесса и копирует в таблицу дескрипторов дочернего процесса все записи, у которых этот флаг установлен (правда для этого надо также установить еще один флаг у функции создания процесса, о которой мы поговорим позднее). При этом счетчики использования скопированных объектов увеличиваются на единицу а записи об объектах помещаются в те же поля таблицы дескрипторов дочернего процесса, в которых они находились у родительского процесса. В результате значения дескрипторов скопированных объектов у родительского и дочернего процессов совпадают.

Рис. Передача дескрипторов объекта при наследовании.

Проблема состоит только в том, что дочерний процесс не знает, какие значения дескрипторов он унаследовал, и должен получить их от родительского процесса. Какой-либо централизованный механизм для этого отсутствует – их можно передать, например, через параметры командной строки, переменные окружения или любым другим способом.

При наследовании происходит передача только тех объектов, которые были открыты родительским процессом в момент вызова функции создания нового процесса. Передать таким способом объекты открытые позже нельзя.

Второй способ позволяет скопировать запись в таблице дескрипторов одного процесса в таблицу дескриптора другого процесса. Это можно сделать в любой момент и процессы не обязаны быть связаны между собой отношением наследования. Осуществить такую операцию может функция DuplicateHandle:

BOOL DuplicateHandle(

HANDLE hSourceProcessHandle, // handle to source process

HANDLE hSourceHandle, // handle to duplicate

HANDLE hTargetProcessHandle, // handle to target process

LPHANDLE lpTargetHandle, // duplicate handle

DWORD dwDesiredAccess, // requested access

BOOL bInheritHandle, // handle inheritance option

DWORD dwOptions // optional actions

);

При работе этой функции может быть задействовано до трех процессов: процесс, из таблицы которого берется запись (SourceProcess); процесс, в таблицу которого запись помещается (TargetProcess); и процесс, который осуществляет вызов функции. Поэтому надо быть внимательным и не перепутать, в контексте какого процесса должны быть определены используемые дескрипторы:

· дескрипторы процессов hSourceProcessHandle и hTargetProcessHandle определены в контексте процесса, вызывающего функцию,

· дескриптор hSourceHandleопределен в контексте процесса SourceProcess,

· дескриптор lpTargetHandleопределен в контексте процесса TargetProcess.

При использовании этой функции в варианте трех процессов возникает задача сначала установить значения всех этих дескрипторов, а потом передать полученное в lpTargetHandle значение второму процессу. Эта задача упрощается, если, например эта функция вызывается процессом-источником или процессом-приемником. Можно ее использовать и для копирования объекта внутри одного процесса. Это может понадобиться, если нам нужно получить копию кого-то из наших объектов с измененными правами доступа.

Наиболее простым, однако, является третий способ. Дело в том, что многие (но не все) из объектов ядра могут иметь имя. У функций, которые создают такой объект (как, например, у функции CreateSemaphore), имеется параметр LPCTSTR lpName // object name. Если передать в качестве значения этого параметра NULL, то мы получим безымянный объект, что никак не поможет нам использовать его в разных процессах. Однако если мы передадим в этом параметре указатель на текстовую строку, то наш объект получит имя. Если какой-либо другой объект попытается создать объект с таким же именем, то операционная система не будет создавать новый объект, а вернет ссылку на наш.

Кроме функции Create… доступ к именованному объекту можно получить с помощью функций Open…. Такие функции есть для всех объектов, которые имеют имя. Рассмотрим, например, функцию OpenSemaphore:

HANDLE OpenSemaphore(

DWORD dwDesiredAccess, // access

BOOL bInheritHandle, // inheritance option

LPCTSTR lpName // object name

);

Эта функция позволяет получить доступ к семафору по его имени. Как можно видеть, в отличие от функции CreateSemaphore здесь нет параметров, задающих начальное состояние и свойства объекта (поскольку он уже создан). Нет тут и указателя на структуру SECURITY_ATTRIBUTES, поскольку мы не можем поменять права доступа к объекту. Вместо этого есть параметр dwDesiredAccess, который определяет, какой режим доступа мы запрашиваем. Дескриптор, полученный с помощью этой функции, может быть унаследован, поэтому флаг bInheritHandle вынесен в качестве отдельного параметра. При вызове функции OpenSemaphore обязательно указать имя объекта в последнем параметре, иначе такая операция не будет иметь смысла.

Отличие функции OpenSemaphore от CreateSemaphore состоит в том, что эта функция не будет создавать новый объект, если в системе нет объекта с указанным именем, а функция создания сделает это.

Использование имен является, пожалуй, самым простым способом получения совместного доступа к системным объектам Windows. Однако при его использовании надо быть осторожным – имена объектов являются общими для всей системы, и при совпадении имен, возможно, что ваша программа будет совместно использовать объекты не только с теми программами, которые вы запланировали. Поэтому при выборе имен для системных объектов следует использовать слова, появления которых в программах других производителей маловероятно. Например, слово Semaphore может использовать любой программист, но маловероятно, чтобы Петя ненамеренно использовал в своей системе название Masha_Semaphore_25. Для генерирования имен можно также использовать случайные числа или, например, системный идентификатор вашего процесса. В этом случае, впрочем, придется придумать способ как передать его другому процессу (например, мы можем показать эту строку пользователю и попросить ввести ее во втором процессе).

 

На этом мы закончим рассмотрение общих свойств системных объектов и перейдем к рассмотрению особенностей работы с конкретными объектами.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.