Чтобы защитить жизненно важные системные данные от доступа и (или) внесения изменений со стороны пользовательских приложений, в Windows используются два процессорных режима доступа (даже если процессор, на котором работает Windows, поддерживает более двух режимов): пользовательский режим и режим ядра.
Код пользовательского приложения запускается в пользовательском режиме, а код операционной системы (например, системные службы и драйверы устройств) запускается в режиме ядра. Режим ядра — такой режим работы процессора, в котором предоставляется доступ ко всей системной памяти и ко всем инструкциям центрального процессора. Предоставляя программному обеспечению операционной системы более высокий уровень привилегий, нежели прикладному программному обеспечению, процессор гарантирует, что приложения с неправильным поведением не смогут в целом нарушить стабильность работы системы.
ПРИМЕЧАНИЕ В архитектурах процессоров x86 и x64 определены четыре уровня привилегий (или четыре кольца) для защиты системного кода и данных от непреднамеренной или злонамеренной перезаписи в результате выполнения кода, имеющего более низкий уровень привилегий. Windows использует уровень привилегий 0 (или кольцо 0) для режима ядра, и уровень привилегий 3 (или кольцо 3) для пользовательского режима. Причина, по которой в Windows используются только два уровня, заключается в том, что в некоторых аппаратных архитектурах, поддерживаемых в прошлом (например, Compaq Alpha и Silicon Graphics MIPS), были реализованы только два уровня привилегий.
Хотя у каждого Windows-процесса есть свое собственное закрытое адресное пространство, код операционной системы и код драйвера устройства, используют одно и то же общее виртуальное адресное пространство. Каждая страница в виртуальной памяти имеет пометку, показывающую, в каком режиме доступа должен быть процессор для чтения и (или) записи страницы. Доступ к страницам в системном пространстве может быть осуществлен только из режима ядра, тогда как доступ ко всем страницам в пользовательском адресном пространстве может быть осуществлен из пользовательского режима.
Станицы, предназначенные только для чтения (например, те страницы, которые содержат статические данные), недоступны для записи из любого режима. Кроме того, при работе на процессорах, поддерживающих защиту той памяти, которая не содержит исполняемого кода (no-execute memory protection), Windows помечает страницы, содержащие данные, как не исполняемые, предотвращая тем самым неумышленное или злонамеренное выполнение кода из областей данных.
32-разрядные версии Windows не защищают закрытую системную память чтения-записи, используемую компонентами операционной системы, запущенными в режиме ядра. Иными словами, в режиме ядра код операционной системы и драйвера устройства имеют полный доступ к системному пространству памяти и могут обойти систему защиты Windows, получив доступ к объектам. Поскольку основная часть кода операционной системы Windows работает в режиме ядра, очень важно, чтобы компоненты, работающие в этом режиме, были тщательно проработаны и протестированы, чтобы не нарушать безопасность системы или не становиться причиной нестабильной работы системы.
Отсутствие защиты также подчеркивает необходимость проявлять особую осторожность при загрузке драйвера устройства стороннего производителя, потому что программное обеспечение, работающее в режиме ядра, имеет полный доступ ко всем данным операционной системы. Этот недостаток стал одной из причин введения в Windows механизма подписи драйверов, который выводит предупреждение пользователю при попытке добавления автоматически настраиваемого (Plug and Play) драйвера, не имеющего подписи (или, при определенной настройке, блокирует добавление такого драйвера). Помимо этого верификатор драйверов — Driver Verifier — помогает создателям драйверов выискивать просчеты (например, переполнение буферов или допущение утечек памяти), способные повлиять на безопасность или стабильность работы системы.
В 64-разрядных версиях Windows политика подписи кода в режиме ядра —Kernel Mode Code Signing (KMCS) — требует, чтобы все 64-разрядные драйверы устройств (не только автоматически настраиваемые) были подписаны криптографическим ключом, присвоенным одним из основных центров сертификации кода.
Пользователь не может напрямую заставить систему установить не подписанный драйвер, даже имея права администратора, за единственным исключением: эти ограничения могут быть отключены вручную во время загрузки системы путем нажатия клавиши F8 и выбора дополнительного параметра загрузки Disable Driver Signature Enforcement (Выключить принуждение к подписыванию драйверов). При этом выключаются водяной знак на обоях для рабочего стола и определенные функции системы управления правами на цифровые материалы — digital rights management (DRM).
В цикле статей «Архитектура системы» будет показано, что пользовательские приложения осуществляют переключение из пользовательского режима в режим ядра при осуществлении вызова системной службы. Например, Windows-функции ReadFile, в конечном счете, необходим вызов внутренней стандартной программы Windows, управляющей чтением данных из файла. Поскольку эта стандартная программа обращается к структурам внутренних системных данных, она должна работать в режиме ядра.
Переход из режима пользователя в режим ядра осуществляется за счет использования специальной инструкции процессора, которая заставляет процессор переключиться в режим ядра и войти в код диспетчеризации системных служб, вызывающий соответствующую внутреннюю функцию в Ntoskrnl.exe или в Win32k.sys. Перед тем как вернуть управление пользовательскому потоку, процессор переключается в прежний, пользовательский режим работы. Таким образом, операционная система защищает саму себя и свои данные от прочтения и модификации со стороны пользовательских процессов.
ПРИМЕЧАНИЕ Переход из пользовательского режима в режим ядра (и назад) не влияет на планирование работы потоков как таковое — переход из режима в режим не является переключением контекста.
Таким образом, пользовательский поток вполне может выполняться часть времени в пользовательском режиме, а другую часть времени — в режиме ядра.
Фактически, из-за того, что основная масса графики и оконная система также работают в режиме ядра, приложения, интенсивно использующие графику, проводят большую часть своего времени в режиме ядра, нежели в пользовательском режиме. Это легко проверить, если запустить приложение, интенсивно использующее графику, например, Microsoft Paint или Microsoft Chess Titans, и посмотреть, как распределяется время между пользовательским режимом и режимом ядра, используя для этого один из счетчиков производительности, перечисленных в таблице.
Более сложные приложения могут использовать такие новые технологии, как Direct2D и создание составных изображений (compositing), которые проводят основной объем вычислений в пользовательском режиме и отправляют ядру только исходные данные поверхностей, сокращая время, затрачиваемое на переходы между пользовательскими режимами и режимами ядра.
Объект: Счетчик | Функция |
---|---|
Процессор: % работы в привилегированном режиме (Processor: % Privileged Time) | Процентный показатель работы отдельного центрального процессора (или всех центральных процессоров) в режиме ядра в течение определенного интервала времени |
Процессор: % работы в пользовательском режиме (Processor: % User Time) | Процентный показатель отдельного центрального процессора (или всех центральных процессоров) в пользовательском режиме в течение определенного интервала времени |
Процесс: % работы в привилегированном режиме (Process: % Privileged Time) | Процентный показатель работы потоков процесса в режиме ядра в течение определенного интервала времени |
Процесс: % работы в пользовательском режиме (Process: % User Time) | Процентный показатель работы потоков процесса в пользовательском режиме в течение определенного интервала времени |
Поток: % работы в привилегированном режиме (Thread: % Privileged Time) | Процентный показатель работы потока в режиме ядра в течение определенного интервала времени |
Поток: % работы в пользовательском режиме (Thread: % User Time) | Процентный показатель работы потока в пользовательском режиме в течение определенного интервала времени |