<<
>>

Пространство имен объектов

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

Пространство имен NT иерархическое, его каталоги и символические ссылки реализуются диспетчером объектов. Пространство имен способно расширяться, что позволяет любому типу объектов создать расширения пространства имен (предоставив процедуру с названием Parse). Процедура Parse — это одна из процедур, которые могут быть предоставлены для каждого типа объектов при создании типа (табл. 11.8).

Таблица 11.8. Процедуры объекта, предоставляемые при определении нового типа объектов

Процедура Open используется редко, поскольку поведение диспетчера объектов по умолчанию — это именно то, что нужно, и поэтому эта процедура определена как NULL почти для всех типов объектов.

Процедуры Close и Delete представляют собой другие фазы работы с объектом. Когда закрывается последний описатель объекта, могут потребоваться действия по очистке состояния (которые выполняются процедурой Close). Когда из объекта удаляется последняя ссылка на указатель, вызывается процедура Delete, чтобы подготовить объект к удалению и утилизировать его память. Для файловых объектов обе эти процедуры реализованы как обратные вызовы в диспетчер ввода-вывода, как раз и являющийся тем компонентом, который объявил тип объекта «файл». Операции диспетчера объектов приводят к соответствующим операциям ввода-вывода, которые посылаются вниз по связанному с файлом стеку устройств (основную работу делает файловая система).

Процедура Parse используется для открытия или создания объектов (вроде файлов и ключей реестра), которые расширяют пространство имен NT. Когда диспетчер объектов пытается открыть объект по имени и встречает листовой узел в той части пространства имен, которой он управляет, он проверяет, указал ли тип для объекта листового узла процедуру Parse. Если указал, то он вызывает эту процедуру, передавая ей неиспользованную часть маршрута. Например, в файловых объектах листовой узел — это объект устройства, представляющий конкретный том файловой системы. Процедура Parse реализована диспетчером ввода-вывода, в результате она приводит к операции ввода-вывода в файловую систему (для заполнения файлового объекта, который будет ссылаться на открытый экземпляр файла на томе, к которому относится маршрут). Мы изучим этот пример по шагам чуть позже.

Процедура QueryName используется для поиска имени, связанного с объектом. Процедура Security используется для получения, настройки или удаления дескрипторов безопасности объекта. Для большинства объектных типов эта процедура предоставляется как стандартная точка входа в компоненте «монитор безопасности» исполнительного уровня.

Обратите внимание на то, что процедуры, указанные в табл. 11.8, самых полезных операций с объектами, таких как чтение или запись файлов (или сброс и установка семафоров), не выполняют.

Вместо этого процедуры диспетчера объектов предоставляют функции, необходимые для правильной настройки доступа к объектам и очистка объектов после прекращения работы с ними. Объекты становятся полезными за счет API-функций, работающих со структурами данных, которые содержатся в объектах. Такие системные вызовы, как NtReadFile и NtWriteFile, используют таблицу описателей процессов, созданную диспетчером объектов для преобразования описателя в ссылочный указатель на исходный объект, например на файловый объект, содержащий данные, необходимые для реализации системных вызовов. Кроме этих обратных вызовов диспетчер объектов предоставляет также набор общих объектных процедур для таких операций, как создание объектов и типов объектов, дублирование описателей, получение указателя со ссылкой из описателя или имени, а также сложение и вычитание количества ссылок на заголовок объекта и NtClose (обобщенная функция, которая закрывает описатели всех типов).

Несмотря на то что пространство имен объектов чрезвычайно важно для работы всей системы, очень мало кто знает о его существовании, поскольку оно не видимо для пользователей без использования специальных инструментов просмотра. Один из таких инструментов — это winobj, который можно получить бесплатно по адресу www.microsoft.com/technet/sysinternals. После запуска этот инструмент показывает пространство имен объектов, которое обычно содержит перечисленные в табл. 11.9 каталоги объектов (а также некоторые другие).

Таблица 11.9. Некоторые стандартные каталоги пространства имен объектов

Таблица 11.9 (продолжение)

Странно названный каталог \?? содержит имена всех устройств в стиле MS-DOS, такие как А: (для флоппи-диска) и С: (для первого жесткого диска).

Эти имена фактически являются символическими ссылками на каталог \Device, где и находятся объекты устройств. Имя \?? было выбрано для того, чтобы оно было первым по алфавиту (для ускорения поиска тех маршрутов, которые начинаются с буквы диска). Содержимое других каталогов объектов должно быть понятно без пояснений.

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

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

Несмотря на то что диспетчер объектов имеет все механизмы для управления жизненным циклом объектов внутри ядра, ни интерфейсы NT API, ни Win32 API не предоставляют ссылочного механизма для работы с описателями в нескольких параллельных потоках пользовательского режима. Таким образом, во многих многопоточных приложениях создаются условия гонки и ошибки, когда они закрывают описатель в одном потоке еще до того, как завершится работа с ним в другом потоке; либо описатель закрывается много раз; либо закрывают такой описатель, который еще используется в другом потоке, и используют его для ссылки на другой объект.

Возможно, Windows API надо было спроектировать таким образом, чтобы для каждого типа объектов требовалось свое API закрытия объекта (а не просто одна общая операция NtClose).

Это по крайней мере снизило бы частоту возникновения ошибок из-за того, что потоки пользовательского режима закрывают не те описатели. Другим решением могло бы быть встраивание поля последовательного номера в каждый описатель (в дополнение к индексу таблицы описателей).

Для того чтобы помочь авторам приложений находить подобные проблемы в их программах, Windows имеет верификатор приложений (application verifier), который разработчики могут скачать с сайта компании Microsoft. Аналогично верификатору для драйверов (который мы опишем в разделе 11.7), верификатор приложений делает подробные проверки правил (чтобы помочь программистам отыскать ошибки, которые могут быть не обнаружены обычным тестированием). Он может также включить режим упорядочивания FIFO для списка свободных описателей, чтобы описатели не использовались сразу же повторно (то есть выключить имеющий более высокую производительность режим LIFO, который обычно используется для таблиц описателей). Предотвращение быстрого повторного использования описателей меняет ситуацию использования операцией неправильного описателя на ситуацию использования закрытого описателя (что несложно обнаружить).

Объект устройства — это один из самых важных и универсальных объектов режима ядра исполнительного модуля. Тип указывается диспетчером ввода-вывода, который наряду с драйверами устройств является основным пользователем объектов устройств. Объекты устройств тесно связаны с драйверами, причем каждый объект устройства обычно имеет ссылку на конкретный объект драйвера, который описывает порядок обращения к процедурам обработки ввода-вывода (для соответствующего устройству драйвера).

Объекты устройств представляют собой аппаратные устройства, интерфейсы, шины, а также логические разделы дисков, дисковые тома и даже файловые системы и расширения ядра (наподобие антивирусных фильтров). Многие драйверы устройств имеют имена, так что к ним можно обращаться без необходимости открывать описатели для экземпляров устройств (как это делается в UNIX). Чтобы проиллюстрировать использование процедуры Parse, мы будем использовать объекты устройств (рис.

11.11).

1. Когда компонент исполнительного уровня (такой, как реализующий собственный системный вызов NtCreateFile диспетчер ввода-вывода) вызывает ObOpen- ObjectByName в диспетчере объектов, то он передает маршрут (в кодировке Unicode) для пространства имен NT (например, \??\C:\foo\bar).

2. Диспетчер объектов выполняет поиск по каталогам и символическим ссылкам и в итоге обнаруживает, что \??\C: относится к объекту устройства (типу, определенному диспетчером ввода-вывода). Объект устройства — это листовой узел в той части пространства имен, которой управляет диспетчер объектов.

3. Затем диспетчер объектов вызывает процедуру Parse для этого типа объектов — это IopParseDevice, реализованная диспетчером ввода-вывода. Она передает не только указатель на найденный объект устройства (для С:), но и остаток строки (\foo\bar).

4. Диспетчер ввода-вывода создает IRP (I/O Request Packet — пакет запроса ввода- вывода), выделяет файловый объект и отправляет запрос в стек устройств ввода- вывода (определенный объектом устройства, который был найден диспетчером объектов).

5. IRP передается вниз по стеку ввода-вывода, пока не достигнет того объекта устройства, который представляет экземпляр файловой системы для С:. На всех стадиях управление передается точке входа в объект драйвера, связанный с объектом устройства на этом уровне. В данном случае используется точка входа для операций CREATE, поскольку запрос дан на создание или открытие файла с названием \foo\bar данного тома).

6. Обнаруженные по мере продвижения IRP к файловой системе объекты устройств представляют драйверы фильтров файловой системы, которые могут модифицировать операции ввода-вывода до того, как они достигнут объекта устройства файловой системы. Обычно эти промежуточные устройства представляют собой расширения системы (наподобие антивирусных фильтров).

7. Объект устройства файловой системы имеет ссылку на объект драйвера файловой системы (например, NTFS). Таким образом, объект драйвера содержит адрес операции CREATE в NTFS.

8. NTFS заполняет файловый объект и возвращает его диспетчеру ввода-вывода, который осуществляет возврат вверх по всему стеку устройств (до тех пор, пока IopParseDevice не вернется в диспетчер объектов — см. раздел 11.8).

9. Диспетчер объектов закончил поиск в пространстве имен. Он получил обратно инициализированный объект из процедуры Parse (который является файловым объектом, а не исходным объектом устройства, который он обнаружил). Таким образом, диспетчер объектов создает описатель для файлового объекта в таблице описателей текущего процесса и возвращает описатель вызывавшей стороне.

10. Последний шаг — возврат к вызвавшей стороне (в пользовательский режим), который в данном случае является процедурой CreateFile интерфейса Win32 API. Она вернет описатель в приложение.

а б

Рис. 11.11. Шаги в диспетчерах ввода-вывода и объектов для создания или открытия файла

и получения описателя файла

Компоненты исполнительного уровня могут создавать новые типы динамически, при помощи вызова интерфейса ОЪСгеа1еОЪ]вс1Туре диспетчера объектов. Не существует исчерпывающего списка типов объектов, и от версии к версии они меняются. Некоторые из наиболее часто используемых в Windows типов перечислены в табл. 11.10. Позвольте кратко рассказать об этих объектных типах.

Таблица 11.10. Некоторые часто встречающиеся объектные типы исполнительного уровня (управляемые диспетчером объектов)
Тип Описание
Process (процесс) Пользовательский процесс
Thread (поток) Поток в процессе
Semaphore (семафор) Вычислительный семафор, используемый для межпроцессной синхронизации
Mutex (мьютекс) Двоичный семафор, используемый для входа в критическую область
Event (событие) Объект синхронизации с постоянным состоянием (сигнализированным или нет)
ALPC Port (Порт ALPC) Механизм для передачи сообщений между процессами
Timer (таймер) Объект, который разрешает потоку бездействовать в течение фиксированного периода времени
Queue (очередь) Объект, который используется для уведомления о завершении асинхронного ввода-вывода
Open file (открытый файл) Объект, который связан с открытым файлом
Access token (маркер доступа) Дескриптор безопасности для некоего объекта
Profile (профиль) Структура данных, используемая для профилирования использования процессора
Section (сегмент) Объект, который используется для представления отображаемых файлов
Key (ключ) Ключ реестра (используется для прикрепления реестра к пространству имен диспетчера объектов)
Object directory (каталог объектов) Каталог для группировки объектов в диспетчере объектов
Symbolic link (символическая ссылка) Ссылается на другой объект диспетчера объектов при помощи маршрута
Device (устройство) Объект устройства ввода-вывода для физического устройства, шины, драйвера или экземпляра тома
Device driver (драйвер устройства) Каждый загруженный драйвер устройства имеет свой объект

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

Объекты порта, таймера и очереди также относятся к обмену и синхронизации. Порты — это каналы между процессами (для обмена сообщениями LPC). Таймеры предоставляют способ блокирования на определенный интервал времени. Очереди (известные внутри системы как KQUEUES) используются для уведомления потоков о том, что ранее начатая операция асинхронного ввода-вывода завершилась, или о том, что в порту ждет сообщение. Очереди созданы для управления уровнем параллелизма в приложении и используются в высокопроизводительных многопроцессорных приложениях, например таких, как серверы систем управления базами данных.

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

Сегменты используются для представления объектов памяти, которые приложения могут попросить у диспетчера памяти отобразить на свое адресное пространство. Они хранят сведения о сегменте файла (или файла подкачки), который представляет страницы объекта памяти (когда они находятся на диске). Ключи представляют для пространства имен реестра точку монтирования в пространстве имен диспетчера объектов. Обычно имеется только один объект ключа (с названием \REGISTRY), который соединяет названия ключей реестра и их значения с пространством имен NT.

Каталоги объектов и символические ссылки являются полностью локальными для той части пространства имен NT, которая управляется диспетчером объектов. Они похожи на свои аналоги в файловой системе: каталоги позволяют собрать вместе связанные между собой объекты. Символические ссылки позволяют имени из одной части пространства имен объектов ссылаться на объект в другой части пространства имен объектов.

Каждое известное операционной системе устройство имеет один (или несколько) объектов устройств, которые содержат информацию о нем и используются системой для ссылок на устройство. И наконец, каждый драйвер устройства (который был загружен) имеет объект драйвера в пространстве объектов. Объекты драйвера совместно используются всеми объектами устройств, которые представляют собой экземпляры устройств, управляемых этими драйверами.

Прочие объекты (не указанные в таблице) служат более специализированным целям (взаимодействие с транзакциями ядра, пул рабочих потоков Win32).

11.3.4.

<< | >>
Источник: Э. ТАНЕНБАУМ Х. БОС. СОВРЕМЕННЫЕ ОПЕРАЦИОННЫЕ СИСТЕМ Ы 4-е ИЗДАНИЕ. 2015

Еще по теме Пространство имен объектов:

  1. Статья 298. Незаконное проведение поисковых работ на объекте археологического наследия, уничтожение, разрушение или повреждение объектов культурного наследия
  2. Два пространства
  3. ПРОСТРАНСТВО: ВОСПРИЯТИЕ
  4. ПРОСТРАНСТВО СЕМАНТИЧЕСКОЕ СУБЪЕКТИВНОЕ
  5. ПРОСТРАНСТВО: ВОСПРИЯТИЕ: НАРУШЕНИЕ
  6. Часть I Пространство движения
  7. 5.10.1. Создание пространства для ответа
  8. ФАЗИРОВАНИЕ ПРОСТРАНСТВА
  9. Утренняя медитация от возлюбленной Сарасвати. Исцеление пространства.
  10. ЛЕКЦИЯ 11 2.2.3. Структура городского пространства
  11. 5.3. КАК ОСВОБОДИТЬ ПРОСТРАНСТВО ДЛЯ СЮРПРИЗА
  12. Структурирование консультативного пространства
  13. Упражнение для восприятия физических пространств