Обзор статьи «Evolution of the PikeOS Microkernel»

Обзор статьи «Evolution of the PikeOS Microkernel»

Just code IT

В своей статье «Evolution of the PikeOS Microkernel» сотрудники SysGo Роберт Кайзер и Стефан Вагнер описывают, как со временем менялась архитектура микроядра PikeOS в ответ на вызовы, связанные с информационной и функциональной безопасностью.

Оказалось, что микроядро PikeOS изначально было практически полным клоном микроядра L4 версии 2.0, но со временем разработчики стали замечать в нем фатальные для их области применения архитектурные недостатки.

Среди этих недостатков авторы называют:

1. отсутствие механизмов ограничения взаимодействия;

2. отсутствие механизмов разграничения прав доступа к сервисам ядра;

3. невозможность гарантировать какой-то процент процессорного времени множеству потоков;

4. невозможность жесткого разделения ресурсов;

5. неконтролируемый рост mapping database;

6. отсутствие стандартных примитивов синхронизации в пространстве пользователя.

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

1. Механизмы ограничения взаимодействия

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

Йохен Лидке, автор оригинального L4, предложил идею механизма Clans and Chiefs, который помогал бы вводить определенные ограничения доступа между отдельными процессами.

В Clans and Chiefs процессы объединяются в группы (кланы), у каждого клана есть свой главный (вождь). Процессы внутри клана могут общаться друг с другом неконтролируемо, но послать сообщение члену другого клана возможно только через вождя.

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

В более поздних микроядрах, наследующих принципы L4, появился иной механизм, основанный на модели Object Capabilities. Но PikeOS появилась еще до того, когда этот подход стал популярным.

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


2. Механизмы ограничения доступа к сервисам ядра

Микроядро L4 по умолчанию предоставляет не так много возможностей ограничения прав доступа, что делает систему не слишком гибкой. Обычно в системах на основе L4 есть главный процесс, запускаемый первым, этот процесс может выполнять высокопривилегированные вызовы к ядру — например, создавать другие процессы. Все остальные процессы должны пользоваться его сервисами по IPC.

Часто таких ограниченных возможностей недостаточно. Авторы PikeOS решили добавить в систему понятие ability. Ability — это право процесса на доступ к определенному набору системных вызовов (что-то похожее на POSIX Capabilities). Каждый процесс получает набор ability от своего родителя, но не может получить больше прав, чем имеет этот родитель.


3. Гарантия доли процессорного времени

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

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

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

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


4. Жесткое разделение ресурсов между группами процессов

В safety critical системах важны статические гарантии. Например, важно понимать, что определенное количество памяти будет гарантированно доступно определенной группе процессов. То есть, важно не только жесткое распределение процессорного времени, но и разделение других ресурсов, таких как память.

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

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


5. Mapping Database

Микроядро L4 — пример очень изящного дизайна API. Эта система невероятно гибка и лаконична. Изначально предполагалось, что процессы в L4 могут получать страницы памяти от своих родителей и других процессов благодаря возможности передавать страницы, прикрепляя их к сообщениям IPC. Так, страницы можно разделять между несколькими процессами, а также отдавать в монопольное использование другим.

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

Это важно, ведь в любой момент можно попытаться отозвать страницы обратно, забрав их у «должников». Очень удобный и красивый механизм.

Тем не менее он подвержен проблеме исчерпания системных ресурсов. Можно написать две вредоносные программы, которые начнут передавать по кругу регион памяти и тем самым неконтролируемо увеличивать объем базы данных отображений. В результате они смогут «съесть» всю доступную память и привести к отказу ядра ОС.

В safety critical системах это неприемлемо, поэтому в PikeOS базу данных отображений упразднили. По наблюдениям разработчиков, возможность отзыва страниц в реальной системе практически не используется, а значит можно отказаться от столь опасной функции.


6. Стандартные примитивы синхронизации

Йохен Лидке был минималистом. Он предполагал, что в пространстве пользователя не требуются какие-либо примитивы синхронизации кроме блокирующего механизма IPC. Нужен мьютекс или семафор для синхронизации доступа к разделяемому ресурсу? Заведите поток, обращаясь к которому по IPC другие потоки будут блокироваться в ожидании сигнала с той стороны! Вот и примитив синхронизации.

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

Разработчики PikeOS решили проблему, введя единственный примитив синхронизации, доступный через системный вызов — событие (event).

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


Заключение

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

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

Report Page