Подсистемы запускаются процессом Диспетчера сеанса — Session Manager (Smss.exe). Информация, касающаяся запуска подсистем, хранится в разделе реестра HKLM\SYSTEM\CurrentControlSet\Control\SessionManager\SubSystems.
Значения, хранящиеся в этом разделе, показаны на рисунке.
Редактор реестра показывает информацию, касающуюся запуска подсистем.
В значении Required перечисляются подсистемы, загружаемые при загрузке системы. Значение содержит две строки: Windows и Debug. Значение Windows содержит спецификацию файла подсистемы Windows, Csrss.exe (от Client/Server Run-Time Subsystem, клиент-серверная подсистема времени выполнения).
Значение Debug оставлено пустым (поскольку оно используется для внутреннего тестирования) и поэтому не вызывает никаких действий. Значение Optional показывает, что по запросу будет запущена подсистема SUA. Значение реестра Kmode содержит имя файла той части подсистемы Windows, которая работает в режиме ядра, Win32k.sys (об этом мы поговорим чуть позже).
Давайте более пристально присмотримся к каждой из подсистем среды окружения.
Содержание:
Подсистема Windows.
Хотя Windows была разработана для поддержки нескольких независимых подсистем среды окружения, с практической точки зрения наличие в каждой подсистеме всего кода для организации многооконного интерфейса и отображения ввода-вывода может привести к большой степени дублированности системных функций, что, в конечном счете, негативно скажется как на размере, так и на производительности системы. Поскольку Windows была первичной подсистемой, разработчики Windows решили поместить эти базовые функции в ней и заставить другие подсистемы для отображения ввода-вывода вызывать подсистему Windows.
Таким образом, подсистема SUA для отображения ввода-вывода вызывает службы в подсистеме Windows.
В результате такого конструкторского решения подсистема Windows является необходимым компонентом для любой Windows-системы, даже на серверных системах без зарегистрированных интерактивных пользователей.
По этой причине процесс помечен как необходимый (стало быть, если по каким-то причинам происходит выход из этого процесса, система дает сбой).
Подсистема Windows состоит из следующих основных компонентов:
- Для каждого сеанса экземпляр процесса подсистемы среды (Csrss.exe) загружает три DLL-библиотеки (Basesrv.dll, Winsrv.dll и Csrsrv.dll), содержащие поддержку:
- создания и удаления процессов и потоков;
- частей, поддерживающих процессы 16-разрядной виртуальной DOS-машины (VDM) (только для 32-разрядной версии Windows);
- Side-by-Side (SxS) сборок (Fusion) и манифестов;
- других разнообразных функций, например GetTempFile, DefineDosDevice, ExitWindowsEx и нескольких естественных функций поддержки языка.
- Драйвер устройства режима ядра (Win32k.sys), включающий в себя:
- диспетчер окон, который управляет выводом окон, осуществляет экранный вывод, получает ввод с клавиатуры, мыши и других устройств и передает приложениям пользовательские сообщения;
- интерфейс графических устройств — Graphics Device Interface (GDI), представляющий собой библиотеку функций для устройств графического вывода. Он включает функции для рисования прямых линий, текста и фигур и для манипулирования графическими объектами;
- оболочки для поддержки набора DirectX, реализуемого в другом драйвере ядра (Dxgkrnl.sys).
- Хост-процесс консоли — console host process (Conhost.exe), — предоставляющий поддержку для консольных (символьных) приложений.
- DLL-библиотеки подсистем (например, Kernel32.dll, Advapi32.dll, User32.dll и Gdi32.dll), которые превращают документированные функции Windows API в соответствующие и большей частью недокументированные вызовы системных служб режима ядра в Ntoskrnl.exe и Win32k.sys.
- Драйверы графических устройств для аппаратно-зависимых драйверов графических дисплеев, драйверов принтеров и драйверов видеомини-портов.
Для создания на дисплее таких элементов управления пользовательского интерфейса, как окна и кнопки, приложения вызывают стандартные USER-функции. Диспетчер окон передает соответствующие требования интерфейсу графических устройств GDI, а тот передает их драйверам графических устройств, где они имеют формат, соответствующий устройству отображения. Для завершения поддержки видеодисплея драйвер дисплея работает в паре с драйвером видеомини-порта.
ПРИМЕЧАНИЕ. В той части оптимизации работ, которая в Windows-архитектуре называется MinWin, DLL-библиотеки подсистем в настоящее время, как правило, состоят из специфических библиотек, реализующих API-наборы, которые затем компонуются вместе в DLL-библиотеку подсистемы и разрешаются с помощью специальной схемы перенаправления.
GDI предоставляет набор стандартных двумерных функций, позволяющих приложениям обмениваться данными с графическими устройствами, ничего не зная об этих устройствах. GDI-функции являются посредниками между приложениями и такими графическими устройствами, как драйверы дисплеев и принтеров.
GDI-интерфейс переводит запросы приложения на графический вывод и отправляет запросы драйверам графического дисплея. Он также предоставляет стандартный интерфейс для приложений для использования различных устройств графического вывода. Этот интерфейс позволяет коду приложения быть независимым от аппаратных устройств и их драйверов.
GDI приспосабливает свои сообщения под возможности устройства, зачастую разделяя запрос на управляемые части. Например, некоторые устройства могут понимать направления рисования эллипса, в то время как другие требуют от GDI интерпретировать команду в виде серии пикселов, размещаемых по соответствующим координатам.
(Дополнительная информация, касающаяся графики и архитектуры видеодрайверов, дана в WindowsDriverKit, в разделе «DesignGuide» главы «Display(AdaptersandMonitors)».)
Поскольку основная часть подсистемы, в частности функции дисплейного ввода-вывода, работает в режиме ядра, сообщения процессу подсистемы Windows отправляются всего лишь несколькими Windows-функциями: создания и завершения процесса и потока, отображения буквы сетевого диска и создания временных файлов. В общем, работающее Windows-приложение не будет вызывать многочисленных переключений к процессу подсистемы Windows (или вообще не будет вызывать таких переключений).
Хост Окна консоли.
В исходной конструкции подсистемы Windows процесс подсистемы (Csrss.exe) отвечал за управление из окон консоли и каждого консольного приложения (например, Cmd.exe, окна командной строки), осуществлявшего обмен данными с Csrss. Теперь Windows использует для каждого окна консоли, имеющего в системе отдельный процесс — хост окна консоли, — console window host (Conhost.exe).
Одно и то же окно консоли может совместно использоваться несколькими консольными приложениями, как при запуске одной командной строки из другой командной строки. По умолчанию вторая командная строка совместно использует окно консоли первой командной строки.
Всякий раз, когда консольное приложение регистрируется с помощью экземпляра подсистемы Csrss, запущенной в текущем сеансе, Csrss создает новый экземпляр Conhost, используя вместо системного маркера Csrss маркер доступа клиентского процесса. Затем подсистема отображает на хосты окна консоли используемый ею общий раздел памяти, чтобы позволить всем хостам Conhost совместно использовать часть их памяти с Csrss для эффективной обработки буфера (их потоки уже не существуют внутри Csrss), и создает поименованный порт асинхронного вызова локальной процедуры (AsynchronousLocalProcedureCall, ALPC) в каталоге объектов управления \RPC .
Имя порту дается в формате console-PIDlpc-handle, где PID является идентификатором Conhost-процесса. Затем происходит регистрация этого PID со структурой процесса ядра, связанной с пользовательским приложением, которое затем может запрашивать эту информацию для открытия только что созданного ALPC-порта. Этот процесс также задает соответствие объекта общего раздела памяти между приложением командной строки и его Conhost, чтобы они могли обмениваться данными.
И наконец, в каталоге BaseNamedObjects сеанса 0 создается событие ожидания (которое называется ConsoleEvent-PID), чтобы приложение командной строки и Conhost смогли уведомить друг друга о новых данных буфера. На следующем рисунке показывается процесс Conhost с дескрипторами, открытыми для его ALPC-порта и события.
Поскольку Conhost работает с полномочиями пользователя (под которыми также подразумевается уровень прав пользователя), так же как в процессе, связанном с самим приложением консоли, процессы консоли защищаются механизмом безопасности, который называется «изоляцией привилегий пользовательского интерфейса» (UserInterfacePrivilegeIsolation).
Кроме этого консольные приложения, ограниченные возможностями центрального процессора, могут быть идентифицированы тем хост-процессом консоли, который их поддерживает (и который пользователь при необходимости может завершить). Поскольку теперь Conhost-процессы запускаются за пределами специального анклава подсистемы Csrss, возникает побочный эффект, благодаря которому консольные приложения (чьими окнами фактически владеет Conhost) могут быть полностью настроены на тему, загружать DLL-библиотеки сторонних производителей и запускаться с полноценными оконными возможностями.