Основные положения микроядерной архитектуры
Микроядерная архитектура является альтернативой рассмотренному выше классическому способу построения ОС. В отличие от традиционной архитектуры, согласно которой ОС представляет собой монолитное ядро, реализующее основные функции по управлению аппаратными ресурсами и организующее среду для выполнения пользовательских процессов, микроядерная архитектура распределяет функции ОС между микроядром и входящими в состав ОС системными сервисами, реализованными в виде процессов, равноправных с пользовательскими приложениями.
Рассмотрим концепцию микроядерной архитектуры построения ОС. Главной особенностью данного подхода является то, что в привилегированном режиме остается работать только очень малая часть ОС, называемая соответственно микроядром. Микроядро защищено от остальных частей ОС и пользовательских приложений. Набор входящих в состав микроядра функций, как правило, соответствует слою базовых механизмов обычного ядра, хотя в состав микроядра включаются далеко не все базовые функции ядра, а только функции управления процессами, обработки прерываний, управления виртуальной памятью, пересылки сообщений, управления устройствами ввода-вывода. Выполнение таких функций ОС практически невозможно реализовать в пользовательском режиме. Все машинно-зависимые модули ОС также включаются в микроядро.
Не вошедшие в состав микроядра высокоуровневые функции и модули ядра оформляются в виде обычных приложений, работающих в пользовательском режиме. При этом на разработчика ОС ложится далеко неоднозначная задача принятия решения о том, какой из модулей будет работать в привилегированном режиме, а какой в пользовательском. Как правило, на это решение сильное влияние оказывает специфика применения данной ОС и критерии, которым она должна удовлетворять. В общем случае многие менеджеры ресурсов, являющиеся неотъемлемой частью ядра ОС с классической архитектурой, остаются за пределами микроядра и работают в пользовательском режиме. На рисунке ниже можно видеть основные различия в построении ОС с монолитным ядром (рис. 5а) и с микроядерной архитектурой (рис. 5б).
Работающие в пользовательском режиме менеджеры ресурсов имеют принципиальные отличия от традиционных утилит ОС и системных обрабатывающих программ ОС, хотя при микроядерной архитектуре все эти программные компоненты также оформлены в виде приложений. Утилиты и обрабатывающие программы вызываются в основном пользователями. Ситуации, когда одному приложению требуется выполнение функции другого приложения, возникают крайне редко, поэтому в ОС с классической архитектурой отсутствует механизм, с помощью которого одно приложение могло бы вызвать функции другого. Принципиально другая ситуация возникает в том случае, если в форме обычного приложения оформляется часть ОС. По определению основным назначением такого приложения является обслуживание запросов других приложений, например создание процесса, выделение памяти, проверка прав доступа к ресурсу и т.д. Вследствие этого вынесенные в пользовательский режим менеджеры ресурсов являются серверами ОС, то есть модулями, основное назначение которых – обслуживание запросов локальных приложений и других модулей ОС. Совершенно очевидно, что при реализации микроядерной архитектуры необходимо обеспечить наличие в ОС удобного и эффективного способа вызова процедур одного процесса из другого. Поддержка такого механизма является одной из главных задач, возложенных на микроядро ОС.
Рассмотрим типичный пример организации механизма обращения приложений к функциям ОС, оформленным в виде серверов (рис. 6).
Клиент, которым может быть как пользовательская прикладная программа, так и другой компонент ОС, запрашивает у соответствующего сервера выполнение некоторой функции, посылая ему сообщение. Следует заметить, что непосредственная передача сообщений между приложениями невозможна, поскольку их адресные пространства изолированы друг от друга. Микроядро ОС, выполняющееся в привилегированном режиме, имеет доступ к адресным пространствам каждого из этих приложений и поэтому может выступать в качестве посредника при передаче сообщений. Микроядро сначала передает сообщение, содержащее имя и параметры вызываемой процедуры соответствующему серверу, затем сервер выполняет запрошенную операцию, после чего микроядро возвращает результаты клиенту посредством другого сообщения. Таким образом, работа микроядерной ОС соответствует известной модели клиент-сервер, в которой роль транспортных средств выполняет микроядро. Стандартизованные протоколы предоставления сервиса или ресурсов позволяют серверу обслуживать клиента независимо от деталей их реализации, что открывает перед разработчиками широкие возможности для построения распределенных систем. Инициатором обмена обычно является клиент, который посылает запрос на обслуживание серверу, находящемуся в состоянии ожидания. Один и тот же процесс может быть клиентом по отношению к одним ресурсам и сервером для других. Данная модель успешно применяется не только при построении ОС, но и при создании программного обеспечения любого уровня. Применение модели клиент-сервер по отношению к ОС состоит в реализации не вошедших в состав ядра компонентов ОС в виде множества серверов, каждый из которых предназначен для обслуживания определенного ресурса (например, управления памятью, процессами, контроля доступа и т. д.). Наиболее полно раскрыть преимущества технологии клиент-сервер позволяет применение методов объектно-ориентированного проектирования и программирования. Если каждый сервер обслуживает только один тип ресурсов и представляет его клиентам в виде некоторой абстрактной модели, то такой сервер можно рассматривать как объект, так как ему присущи все необходимые для этого качества. Объект должен обладать состоянием, поведением и индивидуальностью. Действительно, каждый сервер выполняется в виде отдельного процесса и поэтому обладает индивидуальностью. Для каждого сервера существует четко определенная модель состояний и переходов между ними. И, наконец, “поведение” каждого сервера однозначно регламентируется протоколом его взаимодействия с клиентами. Соответственно, можно создавать модель ОС, построенной по этим принципам, в виде иерархии серверов и моделей представляемых ими ресурсов, а также описывать существующие между ними взаимосвязи с помощью объектных отношений наследования, использования и включения.
Рассмотрим, как на практике применется концепция микроядерной архитектуры построения ОС.
Одной из первых представила понятие микроядра фирма Next, которая использовала в своих компьютерах систему Mach, прошедшую большой путь развития в университете Карнеги-Меллона при содействии Министерства обороны США. Теоретически ее небольшое привилегированное ядро, окруженное службами пользовательского режима, должно было обеспечить беспрецедентную гибкость и модульность. Но на практике это преимущество несколько уменьшилось из-за наличия монолитного сервера ОС UNIX BSD 4.3, который выполнялся в пользовательском пространстве над микроядром Mach. Однако Mach дал Next возможность предоставить службу передачи сообщений и объектно-ориентированные средства, которые предстали перед потребителями в виде элегантного интерфейса пользователя с графической поддержкой конфигурирования сети, системного администрирования и разработки программного обеспечения.
Затем пришла Microsoft Windows NT, рекламировавшая в качестве ключевых преимуществ использования микроядра не только модульность, но и переносимость. Конструкция NT позволила ей применить системы на основе процессоров Intel, MIPS и Alpha (и последующих) и поддерживать симметричную многопроцессорность. Из-за того что NT должна была выполнять программы, написанные для DOS, Windows, OS/2 и ОС, использующих соглашения POSIX, Microsoft выбрала модульность, присущую микроядерному подходу для того, чтобы сделать структуру NT не повторяющей ни одну из существующих ОС. В результате NT поддерживает каждую надстроенную ОС в виде отдельного модуля или подсистемы.
Более современные архитектуры микроядра были предложены Novell, USL, Open Software Foundation, IBM, Apple и др. Одним из основных соперников NT в части микроядер является микроядро Mach 3.0, которое и IBM, и OSF взялись привести к коммерческому виду. Основной соперник Mach – микроядро Chorus 3.0 фирмы Chorus Systems, выбранный USL за основу своих предложений. Это же микроядро будет использоваться в SpringOS фирмы Sun – объектно-ориентированном преемнике ОС Solaris.
Сегодня стало ясно, что имеется тенденция движения от монолитных систем в сторону использования небольших ядер. Именно такой подход уже использовался компаниями QNX Software и Unisys, в течение нескольких лет успешно поставляющих ОС на основе микроядра. ОС QNX фирмы QNX Software обслуживает рынок систем реального времени, а ОС CTOS фирмы Unisys популярна в области банковского дела.
Теперь рассмотрим основные концепции построения двух наиболее популярных систем: Windows NT и UNIX-системы, основанной на микроядре Mach.
Во многих UNIX-подобных системах в качестве основы для построения выбрано микроядро Mach. Разработка прообраза такой структуры началась в 1975 году в университете Карнеги-Меллона. На базе микроядра Mach эмулировались UNIX и другие ОС. Ядро Mach обеспечивает управление памятью, процессами коммуникации и функции ввода-вывода. Идея построения ядра Mach состоит в обеспечении механизмов, необходимых для работы системы, но стратегия использования этих механизмов реализуется на уровне пользовательских процессов. Ядро управляет пятью главными абстракциями:
- процессами;
- нитями;
- объектами памяти;
- портами;
- сообщениями.
Процесс в Mach – это базисная единица распределения ресурсов, он имеет адресное пространство, содержащее текст программы и данные. Нить в Mach является единицей выполнения. Она имеет счетчик команд и набор регистров, связанных с ней. Каждая нить является частью одного процесса.
Межпроцессное взаимодействие в Mach основано на передаче сообщений. Для того чтобы получить сообщение, пользовательский процесс просит ядро создать защищенный почтовый ящик, который называется порт. Порт хранится внутри ядра и способен поддерживать очередь упорядоченного списка сообщений. Очереди не имеют фиксированной длины, но в целях управления потоком для каждого порта отдельно устанавливается пороговое значение в n сообщений, так что всякий процесс, пытающийся послать еще одно сообщение в очередь длины n, приостанавливается для того, чтобы дать порту возможность очиститься.
Каждый процесс может предоставить другому процессу возможность посылать (или получать) сообщения в один из принадлежащих ему портов. Такая возможность реализуется в виде мандата (capability), который включает не только указатель на порт, но и список прав, которыми другой процесс обладает по отношению к данному порту (например, право выполнить операцию послать - send). Все коммуникации в Mach используют этот механизм. Основной целью, которую ставили перед собой разработчики средств коммуникации ядра Mach, являлась поддержка различных стилей коммуникаций в сочетании с надежностью и гибкостью. Коммуникационные средства ядра Mach поддерживают асинхронную передачу сообщений, механизм для реализации распределенных вычислений, потоки байт (streams) и другие способы.
В ядре Mach имеются различные серверы, которые работают поверх него. Наверное, самым важным сервером является программа, которая содержит большое количество кодов BSD UNIX (например, весь код файловой системы). Этот сервер представляет собой основной эмулятор UNIX. Реализация механизма эмуляции UNIX в среде Mach состоит из двух частей – сервера UNIX и библиотеки эмуляции системных вызовов. Когда система стартует, сервер UNIX инструктирует ядро, чтобы оно перехватывало все прерывания системных вызовов и отображало векторы этих прерываний на адреса внутри библиотеки эмуляции процесса UNIX’, по которым расположены обрабатывающие данные вызовы функции. Любой системный вызов, который делается UNIX-процессом, приводит к кратковременной передаче управления ядру, а затем к немедленной передаче управления библиотеке эмуляции. Значения машинных регистров в момент передачи управления библиотеке становятся теми же, что и в момент прерывания. Как только библиотека эмуляции получает управление, она проверяет регистры для того, чтобы определить, какой системный вызов нужно обработать. Затем библиотека делает вызов сервера UNIX, который и должен выполнить эту работу. После завершения обработки вызова пользовательская программа снова получает управление. Эта передача управления не проходит через ядро.
Хотя описанный метод выполнения программ UNIX и кажется запутанным, многочисленные исследования показали, что он работает лучше, чем традиционные монолитные реализации ядра. В дальнейшем работы над Mach будут фокусироваться на разделении сервера UNIX на несколько серверов с более специфическими функциями.
ОС Windows NT с самого начала проектировалась разработчиками компании Microsoft с учетом всех требований, предъявляемых к современным ОС. При разработке ее структуры была в значительной степени использована концепция микроядра. В соответствии с этой идеей ОС разделена на несколько подсистем, каждая из которых выполняет отдельный набор сервисных функций, например сервисы памяти, по созданию процессов или по планированию процессов. Каждый сервер работает в пользовательском режиме, выполняя цикл проверки запроса клиента на одну из его сервисных функций. Клиент, которым может быть либо другая компонента ОС, либо прикладная программа, запрашивает сервис, посылая сообщение на сервер. Микроядро ОС, действуя в привилегированном режиме, доставляет сообщение нужному серверу, затем сервер выполняет операцию, после этого ядро возвращает результат клиенту с помощью другого сообщения.
Структурно Windows NT может быть представлена в виде двух слагаемых: часть ОС, работающая в режиме пользователя, и часть ОС в режиме ядра.
Часть, работающая в режиме ядра, называется executive Windows NT– исполнительной частью. Она включает ряд компонентов, которые управляют виртуальной памятью, объектами (ресурсами), вводом-выводом, файловой системой (включая сетевые драйверы), взаимодействием процессов и частично системой безопасности. Эти компоненты контактируют между собой с помощью межмодульных связей. Каждый компонент вызывает другие с помощью набора тщательно специфицированных внутренних процедур.
Вторую часть, работающую в режиме пользователя, составляют серверы – защищенные подсистемы Windows NT. Серверы Windows NT называются защищенными, так как каждый из них выполняется в отдельном процессе, память которого отделена от других процессов системой управления виртуальной памятью NT executive. Так как подсистемы автоматически не могут совместно использовать память, они общаются друг с другом посредством посылки сообщений. Сообщения передаются как между клиентом и сервером, так и между двумя серверами. Все сообщения проходят через исполнительную часть Windows NT.
Поддержку защищенных подсистем обеспечивает исполнительная часть – Windows NT executive, которая работает в пространстве микроядра и никогда не сбрасывается на диск. Ее составными частями являются:
1) менеджер объектов, создающий, удаляющий и управляющий объектами NT executive – абстрактными типами данных, используемыми для представления ресурсов системы;
2) монитор безопасности, устанавливающий правила защиты на локальном компьютере. Охраняет ресурсы ОС, выполняет защиту и регистрацию исполняемых объектов;
3) менеджер процессов, создающий и завершающий, приостанавливающий и возобновляющий процессы, а также хранящий о них информацию;
4) менеджер виртуальной памяти;
5) подсистема ввода-вывода, включающая в себя следующие компоненты:
- менеджер ввода-вывода, предоставляющий средства ввода-вывода, независимые от устройств;
- файловые системы – NT-драйверы, выполняющие файл-ориентированные запросы на ввод-вывод и транслирующие их в вызовы обычных устройств;
- сетевой редиректор и сетевой сервер – драйверы файловых систем, передающие удаленные запросы на ввод-вывод на машины сети и получающие запросы от них;
- драйверы устройств NT executive – низкоуровневые драйверы, непосредственно управляющие устройством;
- менеджер кэша, реализующий кэширование диска.
Исполнительная часть, в свою очередь, основывается на службах нижнего уровня микроядра NT. В функции микроядра входит:
- планирование процессов;
- обработка прерываний и исключительных ситуаций;
- синхронизация процессоров для многопроцессорных систем;
- восстановление системы после сбоев.
Микроядро работает в привилегированном режиме и никогда не удаляется из памяти. Обратиться к нему можно только посредством прерывания. Микроядро расположено над уровнем аппаратных абстракций (Hardware Abstraction Level, HAL), который концентрирует в одном месте большую часть машинно-зависимых процедур. HAL располагается между NT executive и аппаратным обеспечением и содержит такие детали, как контроллеры прерываний, интерфейсы ввода-вывода и механизмы взаимодействия между процессорами. Такое решение позволяет легко переносить Windows NT с одной платформы на другую путем замены только слоя HAL.
При создании NT разработчики руководствовались задачами повышения производительности и расширения сетевых возможностей, а также требованием поддержки определенного набора прикладных сред. Эта цель была достигнута продуманным разделением функций между модулями микроядра и остальными модулями. Например, передача данных в файловую систему и по сети производится быстрее в пространстве микроядра, поэтому внутри микроядра NT выделены буферы для небольших по объему (от 16 до 32 Кб) операций чтения и записи, являющихся типичными для приложений клиент-сервер и распределенных приложений. Размещение этих функций ввода-вывода внутри микроядра, может, и портит его академичность, но соответствует цели создания NT.
Защищенные подсистемы Windows NT работают в пользовательском режиме и создаются Windows NT во время загрузки ОС. Сразу после создания они начинают бесконечный цикл своего выполнения, отвечая на сообщения, поступающие к ним от прикладных процессов и других подсистем. Среди защищенных подсистем можно выделить подкласс, называемый подсистемами окружения. Подсистемы окружения реализуют интерфейсы приложений ОС (API). Другие типы подсистем, называемые интегральными подсистемами, исполняют функции, необходимые для ОС. Например, большая часть системы безопасности Windows NT реализована в виде интегральной подсистемы, сетевые серверы также выполнены как интегральные подсистемы.
Наиболее важной подсистемой окружения является Win32 – подсистема, которая обеспечивает доступ для приложений к 32-разрядной Windows API. Дополнительно эта система обеспечивает графический интерфейс пользователя и управляет вводом-выводом данных пользователя. Также поддерживаются подсистемы POSIX, OS/2, 16-разрядная Windows и MS-DOS.
Каждая защищенная подсистема работает в режиме пользователя, вызывая системный сервис NT executive для выполнения привилегированных действий в режиме ядра. Сетевые серверы могут выполняться как в режиме пользователя, так и в режиме ядра в зависимости от того, как они разработаны.
Подсистемы связываются между собой путем передачи сообщений. Когда, например, пользовательское приложение вызывает какую-нибудь API-процедуру, подсистема окружения, обеспечивающая эту процедуру, получает сообщение и начинает работать над ней либо обращаясь к микроядру, либо посылая сообщение другой подсистеме. После завершения процедуры подсистема окружения посылает приложению сообщение, содержащее возвращаемое значение. Посылка сообщений и другая деятельность защищенных подсистем невидима для пользователя.
Основным средством, скрепляющим все подсистемы Windows NT в единое целое, является механизм вызова локальных процедур (Local Procedure Call, LPC). LPC представляет собой оптимизированный вариант более общего средства – удаленного вызова процедур (Remote Procedure Call, RPC), которое используется для связи клиентов и серверов, расположенных на разных машинах сети.
Средства LPC поддерживают несколько способов передачи данных между клиентами и серверами: один обычно используется для передачи коротких сообщений, другой – для длинных сообщений, а третий оптимизирован специально для использования подсистемой Win32. Каждая подсистема устанавливает порт – канал связи, посредством которого с ней могут связываться другие процессы.
Windows NT использует защищенные подсистемы для того, чтобы:
- обеспечить несколько программных интерфейсов (API), по возможности не усложняя при этом базовый программный код (NT executive);
- изолировать базовую ОС от изменений или расширений в поддерживаемых API;
- объединить часть глобальных данных, требующихся всем API, и в то же время отделить данные, использующиеся каждым отдельным API от данных других API;
- защитить окружение каждого API от приложений и окружения других API, а также защитить базовую ОС от различных окружений;
- позволить ОС расширяться в будущем за счет новых API.
Таким образом, реализация частей ОС в виде серверов, выполняющихся в режиме пользователя, является важнейшей частью проекта Windows NT, оказывающей глубокое воздействие на функционирование всей системы.
Микроядро NT служит, главным образом, средством поддержки для переносимой основной части ОС – набора пользовательских сред. Концентрация машинно-зависимых программ внутри микроядра делает перенос NT на разнообразные процессоры относительно легким. Но в то время как некоторые микроядра (Mach и Chorus) предполагается поставлять в качестве самостоятельного программного продукта, из ОС Windows NT ядро вряд ли может быть вычленено для отдельного использования. Это является одной из причин того, что некоторые специалисты не считают Windows NT истинно микроядерной ОС в том смысле, в котором таковыми являются Mach и Chorus. Те же критики отмечают также, что NT не исключает, как это положено, все надстроенные службы из пространства ядра и что драйверы устройств в NT по минимуму взаимодействуют с микроядром, предпочитая работать непосредственно с лежащим ниже слоем аппаратной абстракции HAL.