Файл: Debian Таненбаум Бос.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Операционные системы

Добавлен: 29.10.2018

Просмотров: 48031

Скачиваний: 190

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

11.2. Программирование в Windows   

941

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

В мире Win32 для настольных систем приложения развертываются путем запуска 
установщика, являющегося частью приложения. Современные приложения должны 
устанавливаться с использованием Widows-программы AppStore, которая будет раз-
вертывать только те приложения, которые были выложены разработчиками в интернет-
магазин Microsoft. Компания Microsoft использовала ту же самую успешную модель, 
которая была представлена компанией Apple и принята Android. Теперь Microsoft будет 
принимать приложения в магазин, если они прошло проверку, которая, помимо всех 
других проверок, гарантирует, что приложение использует только API-интерфейсы, 
доступные в MSDK.

При запуске современное приложение всегда выполняется в песочнице, назваемой 
AppContainer

. Выполнение процесса в песочнице является безопасной технологией 

изоляции того кода, который вызывает наименьшее доверие, чтобы он не мог свободно 
вмешиваться в систему или пользовательские данные. Windows AppContainer считыва-
ет каждое приложение отдельным пользователем и использует механизмы безопасно-
сти Windows для запрещения приложению доступа к произвольным ресурсам системы. 
Когда приложению требуется доступ к системным ресурсам, задействуются WinRT 
API-интерфейсы, связывающиеся с процессами-посредниками (broker processes), 
которые имеют доступ к большей части системы, например к файлам пользователя.

Как показано на рис. 11.3, подсистемы NT состоят из четырех компонентов: процесса 
подсистемы, набора библиотек, перехватчиков в CreateProcess, а также поддержки 
в ядре. Процесс подсистемы — это просто служба. Единственным его специальным 
свойством является то, что он запускается программой smss.exe (диспетчером сеансов); 
это та программа NT, которая первой запускается в пользовательском режиме — по 
запросу CreateProcess из Win32 или из соответствующего API другой подсистемы. 
Хотя поддерживаются только оставшиеся подсистемы Win32, Windows по-прежнему 
поддерживает модель подсистем, включая процесс подсистемы Win32 csrss.exe.

Набор библиотек реализует как специфичные для подсистемы функции операционной 
системы высокого уровня, так и заглушки процедур, которые ведут обмен между ис-
пользующими подсистему процессами (показаны слева) и самим процессом подсисте-
мы (показан справа). Вызовы процесса подсистемы обычно производятся при помощи 
работающих в режиме ядра средств LPC (Local Procedure Call), которые реализуют 
процедурные вызовы между процессами.

Перехватчик в Win32 (в CreateProcess) определяет подсистему, которая требуется 
программе (для этого он изучает двоичный образ). Затем он делает запрос к smss.exe 
на запуск процесса подсистемы csrss.exe (если он еще не запущен). После этого за за-
грузку программы отвечает процесс подсистемы.


background image

942  

 Глава 11. Изучение конкретных примеров: Windows 8 

Рис. 11.3. Компоненты, используемые для построения подсистем NT

Ядро NT спроектировано таким образом, что оно имеет множество средств общего 
назначения, которые можно использовать для написания специфичных подсистем. 
Однако для правильной реализации любой подсистемы необходим еще и специальный 
код. Например, собственный системный вызов NtCreateProcess реализует дублирование 
процесса для поддержки системного вызова fork подсистемы POSIX, а в ядре Win32 
реализована для таблица строк специального типа (называемых элементами — atoms), 
которая эффективно позволяет процессам совместно использовать предназначенные 
только для чтения строки.

Процессы подсистем — это собственные программы NT, которые используют соб-
ственные системные вызовы ядра NT и ее основных служб, таких как smss.exe и lsass.
exe (локальное администрирование безопасности). Собственные системные вызовы 
содержат межпроцессные средства для управления виртуальными адресами, потоками, 
описателями, а также исключениями, созданными для запуска программ, написанных 
под конкретную подсистему.

11.2.1. Собственный интерфейс прикладного 
программирования NT

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


background image

11.2. Программирование в Windows   

943

приложения для Windows делались на основе Win32 и, таким образом, имели больше 
шансов работать и в Windows на базе MS-DOS, и в Windows на базе NT (поскольку 
Win32 API есть в них обеих).

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

Таблица 11.3. Категории типов объектов режима ядра

Категория объекта

Примеры

Синхронизация

Семафоры, мьютексы, события, порты IPC, очереди 
ввода-вывода

Ввод-вывод

Файлы, устройства, драйверы, таймеры

Программа

Задания, процессы, потоки, сегменты, маркеры

Графический интерфейс пользовате-
ля Win32

Рабочие столы, обратные вызовы приложений

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

В собственном интерфейсе прикладного программирования NT есть вызовы для 
создания новых объектов режима ядра и обращения к уже существующим. Каждый 
(создающий или открывающий объект) вызов возвращает вызывающей стороне опи-
сатель

 (handle). Этот описатель может затем использоваться для выполнения операций 

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

Каждый объект имеет связанный с ним дескриптор безопасности (security descriptor), 
который подробно рассказывает, кто и какие типы операций может выполнять с дан-
ным объектом. При дублировании описателей можно добавить новые ограничения на 
доступ, которые будут специфичными для дублированного описателя. Таким образом, 
процесс может дублировать описатель чтения-записи и превратить его в версию «толь-
ко для чтения» для целевого процесса.

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


background image

944  

 Глава 11. Изучение конкретных примеров: Windows 8 

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

В табл. 11.4 показаны примеры собственных API, которые используют явные описатели 
для манипулирования объектами режима ядра, такими как процессы, потоки, порты 
IPC, а также сегменты (sections), используемые для описания объектов в памяти, 
которые могут отображаться на адресное пространство. NtCreateProcess возвращает 
описатель для вновь созданного объекта, представляющего собой выполняющийся 
экземпляр программы, представленной дескриптором SectionHandleDebugPortHandle 
используется для обмена с отладчиком при передаче ему управления процессом по-
сле исключения (например, деления на нуль или обращения к недопустимому адресу 
памяти). ExceptPortHandle используется для обмена с процессом подсистемы, когда 
возникающие ошибки не обрабатываются подключившимся отладчиком.

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

NtCreateProcess(&ProcHandle, Access, SectionHandle, Debug PortHandle, ExceptPortHandle...)

NtCreateThread(&ThreadHandle, ProcHandle, Access, ThreadContext, CreateSuspended...)

NtAllocateVirtualMemory(ProcHandle, Addr, Size, Type, Protection...)

NtMapViewOfSection(SectHandle, ProcHandle, Addr, Size, Protection...)

NtReadVirtualMemory(ProcHandle, Addr, Size...)

NtWriteVirtualMemory(ProcHandle, Addr, Size...)

NtCreateFile(&FileHandle, FileNameDescriptor, Access...)

NtDuplicateObject(srcProcHandle, srcObjHandle, dstProcHandle, dstObjHandle...)

NtCreateThread принимает ProcHandle, поскольку он может создать поток в любом про-
цессе, для которого у вызывающего процесса есть описатель (при наличии достаточных 
прав доступа). Аналогичным образом NtAllocateVirtualMemoryNtMapViewOfSection
NtReadVirtualMemory и NtWriteVirtualMemory позволяют процессу не только работать 
с его собственным адресным пространством, но и выделять виртуальные адреса, ото-
бражать сегменты, а также читать из виртуальной памяти других процессов или пи-
сать в нее. NtCreateFile — это собственный вызов API для создания нового файла или 
открытия уже существующего. NtDuplicateObject — это вызов API для дублирования 
описателей из одного процесса в другой.

Объекты режима ядра не являются уникальными для Windows. Системы UNIX также 
поддерживают разнообразные объекты режима ядра, такие как файлы, сетевые сокеты, 
конвейеры, устройства, процессы, а также средства межпроцессного обмена, такие как 
совместно используемая память, порты сообщений, семафоры и устройства ввода-вы-
вода. В системах UNIX имеются разные способы именования и доступа к объектам, 
такие как дескрипторы файлов, идентификаторы процессов, целочисленные иденти-
фикаторы для объектов межпроцессного обмена SystemV, а также i-узлы для устройств. 
Реализация каждого класса объектов UNIX является специфичной для этого класса. 
Файлы и сокеты используют не те средства, которые применяются в механизмах меж-
процессного обмена SystemV, процессах или устройствах.


background image

11.2. Программирование в Windows   

945

Объекты ядра в Windows для ссылки на объекты ядра используют унифицированное 
средство на основе описателей и названий пространства имен NT, а также унифициро-
ванную реализацию в центральном диспетчере объектов (object manager). Описатели 
имеет каждый процесс, но, как уже говорилось, они могут дублироваться в другой про-
цесс. Диспетчер объектов позволяет давать объектам имена (при их создании), а затем 
открывать их по имени (чтобы получить описатели для объектов).

Для представления названий в пространстве имен NT (NT namespace) диспетчер объ-
ектов использует Unicode. В отличие от UNIX, система NT обычно не делает различия 
между верхним и нижним регистрами (она сохраняет регистр, но не чувствительна 
к нему
). Пространство имен NT является иерархической коллекцией каталогов, сим-
волических ссылок и объектов.

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

Не только приложения используют объекты, которыми управляет диспетчер объектов. 
Сама операционная система также может создавать и использовать объекты — и делает 
это очень интенсивно. Большинство этих объектов создается для того, чтобы позво-
лить одному компоненту системы сохранить на значительный период времени неко-
торую информацию или передать некоторую структуру данных другому компоненту 
(и при этом использовать имеющуюся в диспетчере объектов поддержку именования 
и времени существования). Например, при обнаружении устройства для его пред-
ставления и логического описания подключения устройства к системе создается один 
или несколько объектов устройств (device objects). Для управления устройством за-
гружается драйвер устройства и создается объект драйвера (driver object), в котором 
представлены свойства устройства и даны указатели на реализованные в нем функции 
для обработки запросов ввода-вывода. После этого ссылка на драйвер внутри опера-
ционной системы делается при помощи использования его объекта. К драйверу можно 
также обратиться непосредственно (по имени), а не косвенно (через управляемые им 
устройства) — например, для установки параметров (которые определяют его работу) 
из режима пользователя.

В отличие от UNIX, которая помещает корень своего пространства имен в файловую 
систему, корень пространства имен NT содержится в виртуальной памяти ядра. Это 
означает, что NT должна воссоздавать свое пространство имен верхнего уровня при 
каждой загрузке системы. Использование виртуальной памяти ядра позволяет NT 
хранить информацию пространства имен без необходимости предварительного запу-
ска файловой системы. Это значительно облегчает также добавление в систему новых 
типов объектов режима ядра, поскольку форматы самих файловых систем не нужно 
модифицировать для каждого нового типа объектов.

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