Единое Ядро ​​Windows

Windows — одна из самых универсальных и гибких операционных систем, она работает на совершенно разных архитектурах и доступна в разных вариантах.

Сегодня он поддерживает архитектуры x86, x64, ARM и ARM64. Окна в мое время поддерживается Itanium, PowerPC, DEC Alpha и MIPS. Кроме того, Windows поддерживает ряд SKU, которые работают в разных средах; от центров обработки данных, ноутбуков, Xbox и телефонов до встроенных версий Интернета вещей, таких как банкоматы.

Самым удивительным аспектом является то, что ядро Windows остается практически неизменным во всех этих архитектурах.

Артикул .

Ядро динамически масштабируется в зависимости от архитектуры и процессора, на котором оно работает, чтобы использовать все возможности оборудования.

Конечно, в ядре есть определенное количество кода, специфичного для конкретной архитектуры, но оно минимально, что позволяет Windows работать на самых разных архитектурах.

В этой статье я расскажу об эволюции ключевых частей ядра Windows, позволяющих прозрачно масштабировать его с маломощного чипа NVidia Tegra, работающего на Поверхность РТ 2012, до гиганта монстры , работающий в центрах обработки данных Azure.

Единое ядро ​​Windows

Диспетчер задач Windows, работающий на предварительной версии компьютера класса Windows DataCenter с 896 ядрами, поддерживающими 1792 логических процессора и 2 ТБ памяти.



Ээволюция одного ядра

Прежде чем обсуждать детали ядра Windows, давайте сделаем небольшой экскурс.

рефакторинг .

Рефакторинг играет ключевую роль в увеличении повторного использования компонентов ОС на разных SKU и платформах (например, клиенте, сервере и телефоне).

Основная идея рефакторинга — разрешить повторное использование одних и тех же DLL в разных SKU, поддерживая небольшие модификации, сделанные специально для нужного SKU, без переименования DLL и без поломки приложения.

В основе технологии рефакторинга Windows лежит малодокументированная технология под названием « Наборы API ".

Наборы API — это механизм, который позволяет ОС отделить библиотеки DLL от места их использования.

Например, набор API позволяет Win32-приложениям продолжать использовать kernel32.dll, несмотря на то, что реализация всех API написана на другом языке.

DLL. Реализация этих DLL также может различаться в зависимости от SKU. Вы можете увидеть наборы API в действии, запустив обход зависимостей в традиционной DLL Windows, например, kernel32.dll.

Единое ядро ​​Windows

Закончив отступление о том, как Windows устроена так, чтобы максимизировать повторное использование и совместное использование кода, давайте перейдем к техническим глубинам планирования ядра, которое является ключом к масштабированию ОС.



Компоненты ядра

Windows NT, по сути, микроядро , в том смысле, что он имеет собственное ядро ядра (KE) с ограниченным набором функций, использующее исполнительный уровень (Ex) для выполнения всех политик высокого уровня.

EX по-прежнему является режимом ядра, поэтому на самом деле это не микроядро.

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

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

Единое ядро ​​Windows

Чтобы лучше представить размер компонентов, вот примерная разбивка по количеству строк кода в нескольких ключевых каталогах дерева исходников ядра (включая комментарии).

В таблице нет многого, что связано с ядром.

Подсистемы ядра Строки кода
Менеджер памяти 501, 000
Реестр 211,000
Власть 238,000
Исполнительный 157,000
Безопасность 135,000
Ядро 339,000
Подсистема процесса 116,000
Дополнительную информацию об архитектуре Windows см.

в серии книг « Внутреннее устройство Windows ”.



Планировщик

Подготовив таким образом почву, давайте немного поговорим о планировщике, его эволюции и о том, как ядро Windows способно масштабироваться на стольких различных архитектурах с таким количеством процессоров.

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

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

Таким образом, поток выполняется с высоким приоритетом, оставаясь при этом интерактивным.

Когда он становится привязанным к ЦП, его приоритет падает и возвращается к нему после того, как другие потоки с высоким приоритетом получили свое процессорное время.

Кроме того, ядро случайным образом повышает приоритет готовых потоков, не получивших процессорного времени в течение определенного периода, чтобы не допустить их голодания и исправить инверсию приоритетов.

Планировщик Windows изначально имел одну очередь готовности, из которой он выбирал для запуска следующий поток с наивысшим приоритетом.

Однако по мере того, как стало поддерживаться все больше и больше процессоров, единая очередь стала узким местом, и к выпуску Windows Server 2003 планировщик изменил свою работу и организовал одну очередь готовности для каждого процессора.

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

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

Этот подход оправдал себя до тех пор, пока Windows не начала переходить на процессоры с низким энергопотреблением, например, в ноутбуках и планшетах.

В таких системах, когда не выполнялся поток с наивысшим приоритетом (например, поток пользовательского интерфейса переднего плана), это приводило к заметным сбоям пользовательского интерфейса.

Поэтому в Windows 8.1 планировщик был переведен на гибридную модель с попроцессорными очередями для потоков, связанных с этим процессором, и общей очередью готовых процессов для всех процессоров.

Это не оказало заметного влияния на производительность из-за других изменений в архитектуре планировщика, таких как рефакторинг блокировки базы данных диспетчера.

В Windows 7 появилась такая вещь, как динамический планировщик справедливого распределения (DFSS); в первую очередь это касалось терминальных серверов.

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

Поскольку планировщик не учитывал сеансы и просто использовал приоритет для распределения потоков, пользователи в разных сеансах могли влиять на работу пользователей в других сеансах, ограничивая их потоки.

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

Была предпринята попытка добавить в планировщик правило, согласно которому каждая сессия считалась равной другим по количеству процессорного времени.

Аналогичный функционал имеется и в ОС Linux с их абсолютно честным планировщиком ( Полностью честный планировщик ).

В Windows 8 эта концепция была обобщена в группу планировщиков и добавлена в планировщик, в результате чего каждый сеанс оказался в независимой группе.

Помимо определения приоритетов потоков, планировщик использует группы планировщиков в качестве индекса второго уровня при принятии решения, какой поток запускать следующим.

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

Кроме того, такие группы используются и для более точного контроля над процессами.

В Windows 8 задания были улучшены для поддержки Управление временем процессора .

Используя специальный API, вы можете решить, сколько процессорного времени может использовать процесс, должен ли это быть мягкий или жесткий предел, и получать уведомления, когда процесс достигает этих пределов.

Это похоже на управление ресурсами в контрольные группы на Линуксе.

Начиная с Windows 7, появился Windows Server. поддержка более 64 логических процессоров на одном компьютере.

Чтобы добавить поддержку такого большого количества процессоров, в системе введена новая категория «группа процессоров».

Группа — постоянный набор логических процессоров численностью не более 64 штук, которые рассматриваются планировщиком как вычислительная единица.

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

Один процесс можно разделить на несколько групп (например, экземпляр SQL-сервера); один поток одновременно может выполняться только в пределах одной группы.

Но на машинах с более чем 64 ядрами ЦП в Windows начали возникать новые узкие места, которые не позволяли ресурсоемким приложениям, таким как SQL Server, линейно масштабироваться в зависимости от количества ядер ЦП.

Поэтому даже с добавлением новых ядер и памяти замеры скорости не показали существенного прироста.

Одной из главных проблем, связанных с этим, стал спор по поводу блокировки базы контролера.

Блокировка диспетчерской базы защищенного доступа к объектам, работу которых необходимо запланировать.

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

Под давлением необходимости решения таких проблем в Windows 7 была проведена работа по удалению базовой блокировки менеджера и замене ее более точными настройками, такими как пообъектная блокировка.

Это позволило проводить измерения производительности, такие как SQL. ТПК-С , демонстрируют прирост скорости на 290% по сравнению с предыдущей схемой на некоторых конфигурациях.

Это был один из крупнейших приростов производительности в истории Windows благодаря одному изменению функции.

Windows 10 принесла еще одно нововведение, представив наборы процессоров ( Наборы ЦП ).

Наборы ЦП позволяют процессу разделить систему так, чтобы процесс можно было распределить по нескольким группам процессоров, предотвращая их использование другими процессами.

Ядро Windows даже не позволяет прерываниям устройств использовать процессоры, входящие в ваш набор.

Это гарантирует, что даже устройства не смогут запускать свой код на процессорах, выделенных вашей группе приложений.

Это как низкотехнологичная виртуальная машина.

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

Наконец мы подошли к поддержке ARM64. появился в Windows 10 .

Архитектура ARM поддерживает архитектуру большой маленький , гетерогенный по своей природе – «большое» ядро работает быстро и потребляет много энергии, а «маленькое» ядро работает медленно и потребляет меньше.

Идея в том, что неважные задачи можно выполнять на небольшом ядре, экономя таким образом батарею.

Для поддержки архитектуры big.LITTLE и увеличения времени автономной работы при работе Windows 10 на ARM в планировщик добавлена поддержка гетерогенного планирования с учетом пожеланий приложения, работающего с архитектурой big.LITTLE. Под принятием желаемого за действительное я подразумеваю, что Windows пытается хорошо обслуживать приложения, отслеживая потоки, работающие на переднем плане (или те, у которых мало процессорного времени), и гарантируя, что они выполняются на «большом» ядре.

Все фоновые задачи, службы и другие вспомогательные потоки выполняются на небольших ядрах.

Также в программе вы можете знак силы неважность потока, заставляющая его работать на небольшом ядре.

Работа от имени.

В Windows довольно большая часть работы на переднем плане выполняется другими службами, работающими в фоновом режиме.

Например, при поиске в Outlook сам поиск осуществляется фоновой службой Indexer. Если мы просто запустим все сервисы на небольшом ядре, пострадает качество и скорость приложений на переднем плане.

Чтобы предотвратить замедление работы архитектур big.LITTLE в этих сценариях, Windows отслеживает вызовы приложений, выполняемые другими процессами, чтобы выполнять работу от их имени.

В этом случае мы отдаем приоритет потоку, принадлежащему сервису, и заставляем его выполняться на большом ядре.

Позвольте мне закончить первую статью о ядре Windows, в которой дается обзор того, как работает планировщик.

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

Теги: #Разработка Windows #microsoft #Windows #операционные системы #ядро #Системное программирование #ядро #ОС

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.