Добавлен: 29.10.2018
Просмотров: 48019
Скачиваний: 190
966
Глава 11. Изучение конкретных примеров: Windows 8
глушечными процедурами библиотек (которые работают во всех процессах) и про-
цессом подсистемы, который реализует средства, являющиеся обычными для данного
«персонажа» операционной системы (такого как Win32 или POSIX).
В Windows 8 реализована служба рассылок-подписок под названием WNF (Windows
Notification Facility — средство уведомлений Windows). WNF-уведомления основаны
на изменениях в экземпляре данных состояния WNF. Система рассылки (издатель)
объявляет экземпляр данных состояния (объемом до 4 Кбайт) и сообщает операцион-
ной системе, как долго нужно поддерживать этот экземпляр (например, до следующей
перезагрузки или постоянно). Издатель с помощью атомарной операции обновляет
состояние соответствующим образом. Подписчик может быть нацелен на запуск кода,
как только издатель изменит экземпляр состояния. Поскольку экземпляр состояния
WNF содержит фиксированный объем заранее выделенных данных, никаких очередей
данных, как в основанных на сообщениях IPC со всеми их сопутствующими проблема-
ми в управлении ресурсами, здесь нет. Подписчикам гарантируется лишь то, что они
могут увидеть самую последнюю версию экземпляра состояния.
Этот основанный на состоянии подход дает WNF принципиальное преимущество над
механизмами IPC: издатели и подписчики разобщены и могут запускаться и оста-
навливаться независимо друг от друга. Издателям не нужно выполняться во время
начальной загрузки только для того, чтобы инициализировать их экземпляры состо-
яний, поскольку те могут сохраняться операционной системой между перезапусками.
Подписчики при запуске, как правило, не должны беспокоиться о прошлых значениях
экземпляров состояний, поскольку все, что они должны знать об истории состояний,
инкапсулировано в текущем состоянии. В сценариях, где значения прошлых состояний
не могут по каким-то разумным причинам быть инкапсулированы, текущее состояние
может предоставить метаданные для управления историческим состоянием, скажем,
в файле или в постоянном объекте раздела, используемом в качестве кольцевого бу-
фера. WNF является частью исходных NT API-интерфейсов и не выставляется (пока)
через интерфейсы Win32. Но это средство широко используется внутри системы для
реализации API-интерфейсов Win32 и WinRT.
В Windows NT 4.0 большая часть связанного с графическим интерфейсом Win32 кода
была перенесена в ядро, поскольку оборудование в то время не могло дать требуемой
производительности. Этот код ранее находился в процессе подсистемы csrss.exe, кото-
рый реализует интерфейсы Win32. В ядре код графического интерфейса пользователя
находится в специальном драйвере ядра (win32k.sys). Это изменение должно было
повысить производительность Win32, поскольку при этом исключались дополнитель-
ные переходы из пользовательского режима в режим ядра и стоимость переключения
адресных пространств (для реализации обмена через LPC). Но получилось это не так
хорошо, как ожидалось, поскольку требования для выполняющегося в ядре кода очень
высоки, а дополнительные издержки работы в режиме ядра перевешивают преимуще-
ства снижения стоимости переключений.
Драйверы устройств
Последняя часть на рис. 11.4 — это драйверы устройств (device drivers). Драйверы
устройств в Windows — это динамически связываемые библиотеки, которые загружают-
ся исполнительным уровнем NTOS. Несмотря на то что они в основном используются
для реализации драйверов оборудования (такого, как физические устройства и шины
ввода-вывода), механизм драйверов устройств используется также как средство рас-
11.3. Структура системы
967
ширения режима ядра. Как уже указывалось, большая часть подсистемы Win32 за-
гружается как драйвер.
Диспетчер ввода-вывода организует маршрут потока данных для каждого экземпляра
устройства (рис. 11.7). Этот маршрут называется стеком устройства (sevice stack)
и состоит из закрытых экземпляров выделенных маршруту объектов устройств (device
objects) ядра. Каждый объект устройства в стеке устройств связан с конкретным объ-
ектом драйвера, который содержит таблицу процедур (используемых для пакетов за-
проса ввода-вывода, которые движутся через стек устройства). В некоторых случаях
устройства стека представляют собой драйверы, единственной целью которых является
фильтрация
(filter) операций ввода-вывода (нацеленных на конкретное устройство,
шину или сетевой драйвер). Фильтрация используется по нескольким причинам. Ино-
гда предварительная или последующая обработка операций ввода-вывода приводит
к получению более четкой архитектуры, в других случаях это просто практическое
решение, поскольку отсутствуют права для модификации драйвера и фильтрация
используется для обхода невозможности изменения этих драйверов. Фильтры могут
также реализовывать совершенно новые функциональные возможности, такие как
превращение дисков в разделы или нескольких дисков — в тома RAID.
Рис. 11.7. Упрощенное изображение стеков устройств для двух томов NTFS. Пакет запроса
ввода-вывода передается снизу стека. На каждом уровне стека вызываются соответствующие
процедуры драйверов. Сами стеки устройств состоят из объектов устройств,
выделенных конкретно каждому стеку
968
Глава 11. Изучение конкретных примеров: Windows 8
Файловые системы загружаются как драйверы. Каждый экземпляр тома файловой
системы имеет объект устройства, созданный как часть стека устройств для этого
тома. Этот объект устройства будет связан с объектом драйвера для файловой системы
(подходящим для формата тома). Специальные драйверы фильтрации, называемые
драйверами фильтрации файловой системы
(file system filter drivers), могут вставлять
объекты устройств перед объектами устройств файловой системы (чтобы добавить
в посылаемые к тому запросы ввода-вывода функциональность, такую как проверка
читаемых или записываемых данных на наличие вирусов).
Сетевые протоколы (такие, как IPv4/IPv6 в Windows) также загружаются как драйве-
ры (с использованием модели ввода-вывода). Для совместимости со старыми версиями
Windows на базе MS-DOS драйвер TCP/IP реализует специальный протокол для об-
мена с сетевыми интерфейсами (поверх модели ввода-вывода Windows). Есть и другие
драйверы, которые также реализуют эту схему, в Windows их называют мини-портами
(mini-ports). Совместно используемая функциональность находится в драйвере класса.
Например, общая функциональность для дисков SCSI и IDE, а также USB-устройств
предоставляется драйвером класса, с которым драйверы мини-портов для каждого типа
устройств связываются как с библиотекой.
Мы не будем обсуждать в этой главе никакие конкретные драйверы устройств, но да-
дим в разделе 11.7 больше подробностей о взаимодействии диспетчера ввода-вывода
с драйверами устройств.
11.3.2. Загрузка Windows
Для того чтобы операционная система начала работать, требуется выполнить несколько
шагов. Когда компьютер включается, оборудование инициализирует процессор, кото-
рый начинает выполнять программу в памяти. Однако единственным доступным кодом
в этот момент является код в энергонезависимой памяти, который инициализируется
изготовителем компьютера и иногда обновляется пользователем путем перепрошивки
(flashing). Поскольку программа сохраняется в памяти и обновляется крайне редко, она
называется прошивкой. Прошивка загружается на персональные компьютеры произ-
водителем либо материнской платы, либо компьютерной системы. Исторически сло-
жилось так, что прошивкой персонального компьютера была программа под названием
BIOS (Basic Input/Output System — базовая система ввода-вывода), но на самых новых
компьютерах используется UEFI (Unified Extensible Firmware Interface — унифици-
рованный расширяемый интерфейс прошивки). UEFI является улучшением BIOS
за счет поддержки современного оборудования, предоставления более модульной, не
зависимой от типа центрального процессора архитектуры и поддержки расширяемой
модели, упрощающей начальную загрузку по сети, подготовку к работе новых машин
и запуск диагностики.
Главное предназначение любой прошивки — запуск операционной системы путем
начальной загрузки небольшой специальной программы, которая находит начало
дисковых разделов. Программы начальной загрузки Windows знают, как считать до-
статочно информации с тома файловой систмы или сети, чтобы найти автономную
Windows-программу BootMgr. Программа BootMgr определяет, была ли система ранее
переведена в состояние гибернации или ожидания (это специальные режимы энер-
госбережения, которые позволяют системе «просыпаться» без перезапуска с самого
начала процесса начальной загрузки). Если это так, то BootMgr загружает и выполня-
11.3. Структура системы
969
ет WinResume.exe. В противном случае она загружает и выполняет WinLoad.exe для
выполнения новой загрузки. WinLoad загружает в память загрузочные компоненты
системы: ядро и программу исполнительного уровня (обычно это ntoskrnl.exe), HAL
(hal.dll), содержащий раздел SYSTEM файл, драйвер Win32k.sys (содержащий части
режима ядра подсистемы Win32), а также образы любых других драйверов, которые
перечислены в разделе SYSTEM как загрузочные драйверы (boot drivers) (это озна-
чает, что они нужны во время загрузки системы). Если в системе имеется включенный
Hyper-V, WinLoad также загружает и запускает программу гипервизора.
После загрузки в память загрузочных компонентов Windows управление передает-
ся коду низкого уровня в NTOS, который начинает инициализировать HAL, ядро
и исполнительный уровень, привязывать образы драйверов, а также обращаться
к данным конфигурации в разделе SYSTEM (и обновлять их). После инициализа-
ции всех компонентов режима ядра создается первый процесс пользовательского
режима (использующий для выполнения программу smss.exe, которая подобна
/etc/
init
в системах UNIX).
Самые последние версии Windows предоставляют поддержку усиления безопасности
системы во время начальной загрузки. На многих новейших персональных компью-
терах имеется доверенный платформенный модуль (Trusted Platform Module (TPM)),
представляющий собой микросхему на материнской плате. Эта микросхема является
безопасным криптографическим процессором, защищающим секреты, например ключи
для ширования и дешифровки. Системный TPM может использоваться для защиты
системных ключей, например тех, которые используются BitLocker для шифрования
диска. Защищенные ключи не показывают операционной системе до тех пор, пока
TPM не проведет проверку того, что взломщик не смог их подделать. Этот модуль
может также предоставить другие криптографические функции, например убедить
удаленные системы в том, что операционная система на этом локальном компьютере
не была дискредитирована.
Загрузочные программы Windows могут обработать часто встречающиеся при загруз-
ке проблемы. Иногда инсталляция плохого драйвера устройства или использование
программы вроде regedit (которая может повредить раздел SYSTEM) могут привести
к невозможности нормальной загрузки системы. Есть возможность проигнорировать
недавно внесенные изменения и загрузиться с последней хорошей конфигурацией
системы. Есть и другие варианты загрузки: в безопасном режиме (safe-boot), когда
отключается множество необязательных драйверов, через консоль восстановления
(recovery console), когда появляется окно командной строки
cmd.exe
, предоставляющее
среду, аналогичную однопользовательскому режиму UNIX.
Часто встречается еще одна проблема: компьютеры, на которых установлена система
Windows, могут быть ненадежны, при этом часто происходят отказы как системы, так
и приложений. Данные из программы анализа таких отказов (Microsoft’s On-line Crash
Analysis) говорят о том, что многие такие отказы происходят от плохих модулей па-
мяти, поэтому процесс загрузки Windows Vista предоставляет вариант с выполнением
тщательной диагностики памяти. Возможно, в будущем оборудование персональных
компьютеров на платформе x86 будет стандартно поддерживать модули памяти с ис-
правлением ошибок (ЕСС), однако в настоящее время большинство настольных
компьютеров, ноутбуков и карманных систем уязвимо даже для одиночных ошибок
в одном разряде (которые могут произойти в любом из миллиардов битов имеющейся
в них памяти).
970
Глава 11. Изучение конкретных примеров: Windows 8
11.3.3. Реализация диспетчера объектов
Диспетчер объектов — это, вероятно, самый важный компонент исполнительного
уровня Windows, и именно поэтому мы уже рассмотрели многие его концепции. Как
описывалось ранее, он предоставляет унифицированный интерфейс для управления
ресурсами системы и структурами данных, такими как открытые файлы, процессы,
потоки, сегменты памяти, таймеры, устройства и семафоры. Даже более специали-
зированные объекты (такие, как транзакции ядра, профили, маркеры безопасности
и рабочие столы Win32) управляются диспетчером объектов. Объекты устройств свя-
зывают описания системы ввода-вывода (включая связь между пространством имен
NT и томами файловой системы). Диспетчер конфигурации использует объект типа
Key
для связи с разделами реестра. Сам диспетчер объектов имеет такие объекты, ко-
торые он использует для управления пространством имен NT и реализации объектов
при помощи обычных средств. Это каталоги, символические ссылки, а также объекты
«объект — тип».
Обеспечиваемое диспетчером объектов единообразие имеет различные аспекты. Все
эти объекты используют один и тот же механизм для создания, уничтожения и учета
в системе квот. Ко всем этим объектам можно обращаться из процессов пользователь-
ского режима при помощи описателей. Существует унифицированное соглашение для
управления указателями, ссылающимися на объекты из ядра. Объектам можно давать
имена в пространстве имен NT (которое управляется диспетчером объектов). Объекты
диспетчеризации (которые начинаются с обычной структуры данных для сигнализации
событий) могут использовать обычные интерфейсы синхронизации и уведомления
(вроде WaitForMultipleObjects). Существует обычная система безопасности с исполь-
зованием списков управления доступом (ACL), обязательная для открываемых по
имени объектов, а также проверки доступа при каждом использовании описателя. Есть
даже средства (для трассировки использования объектов) для помощи разработчикам
режима ядра при отладке программ.
Чтобы понять объекты, надо усвоить, что (исполнительный) объект — это просто струк-
тура данных в виртуальной памяти, доступная режиму ядра. Эти структуры данных
обычно используются для представления более абстрактных концепций. Например,
объекты файлов исполнительного уровня создаются для каждого экземпляра файла
файловой системы, который был открыт, объекты процессов создаются для представ-
ления каждого процесса.
Следствием того факта, что объекты являются всего лишь структурами данных ядра,
является то, что при перезагрузке (или сбое) системы все объекты теряются. Когда
система загружается, в ней совсем нет объектов (даже дескрипторов типов объектов).
Все типы объектов (и сами объекты) должны создаваться динамически другими ком-
понентами исполнительного уровня (путем вызова предоставляемых диспетчером
объектов интерфейсов). После создания объектов и указания имени на них можно
ссылаться через пространство имен NT. Поэтому построение объектов по мере загрузки
системы также создает и пространство имен NT.
Объекты имеют структуру (рис. 11.8). Каждый объект содержит заголовок с опреде-
ленной информацией, общей для всех объектов всех типов. Поля этого заголовка вклю-
чают имя объекта, каталог объекта (в котором он находится в пространстве имен NT),
а также указатель на дескриптор безопасности, представляющий список управления
доступом (ACL) для объекта.