Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
У. Столлингс ГЛАВА 4 Потоки.doc
Скачиваний:
49
Добавлен:
11.05.2015
Размер:
6.22 Mб
Скачать

Производительность микроядра

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

Многое зависит от размеров и функциональных возможностей микроядра. В [LIED96a] подытожены результаты некоторых исследований, свидетельствующие о значительной потере производительности в так называемых микроядрах перво­го поколения. От этих потерь не удается избавиться, несмотря на усилия, направленные на оптимизацию кода микроядра. В попытке решить проблему раз­работчики увеличивали микроядро, снова включая в операционную систему критические серверы и драйверы. Основными примерами такого подхода явля­ются операционные системы Mach и Chorus. Избирательное увеличение функ­циональности микроядра приводит к снижению количества переключений меж­ду пользовательским режимом и режимом ядра, а также переключений адрес­ных пространств процессов. Хотя такой подход и снижает потери производительности, это происходит за счет сильных сторон архитектуры опера­ционной системы с микроядром: минимальных интерфейсов, гибкости и т.п.

Другой подход состоит в том, чтобы сделать микроядро не больше, а еще меньше. В [LIED96b] приводятся данные о том, что в микроядре, обладающем надлежащей архитектурой, удается избежать потерь производительности и наряду с этим повысить его гибкость и надежность. Чтобы вы имели представле­ние о размерах микроядер, заметим, что типичное микроядро первого поколения состоит из 300 Кбайт кода и содержит в себе до 140 интерфейсов системных вы­зовов. Примером маленького микроядра второго поколения является ядро опе­рационной системы L4 [HART97, LIED95], которое состоит из 12 Кбайт кода и содержит в себе 7 интерфейсов системных вызовов. Опыт работы с такими сис­темами показывает, что они являются не менее, а иногда даже более, эффектив­ными, чем такие мощные системы, как UNIX.

Архитектура микроядер

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

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

Низкоуровневое управление памятью

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

Впервые идея о том, что системы страничной организации памяти и управ­ления виртуальной памятью можно вынести за пределы ядра, появилась вместе с- внешней системой страничной организации операционной системы Mach [YOUN87]. Принцип работы этой системы поясняется на рис. 4.11. Когда поток приложения обращается к странице, которая отсутствует в основной памяти, возникает прерывание из-за отсутствия страницы, и управление перехватывается ядром. После этого ядро отправляет системе страничной организации сообщение, в котором указывается запрашиваемая страница. Система страничной организа­ции может принять решение загрузить данную страницу и выделить для этого страничный блок. Система страничной организации и ядро должны взаимодей­ствовать между собой, чтобы логические операции, которые происходят в этой системе, отображались в физическую память. Как только нужная страница ста­нет доступна, система страничной организации отправляет приложению сообще­ние о том, что оно может продолжить работу.

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

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

  • Предоставление (grant). Владелец адресного пространства (процесс) может предоставлять некоторые свои страницы другому процессу. Ядро удаляет эти страницы из адресного пространства первого процесса и передает их второму процессу.

  • Отображение (mар). Процесс может отображать любые свои страницы в ад­ресное пространство другого процесса, после чего оба процесса будут иметь доступ к этим страницам. При этом создается общая область памяти, совме­стно используемая двумя процессами. Ядро не меняет информацию о принадлежности первоначальному процессу-владельцу, но при этом выполняет отображение, предоставляющее другому процессу доступ к этим страницам.

  • Восстановление (flush). Процесс может восстановить любые страницы, предос­тавленные другим процессам или отображенные в их адресное пространство.

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

Взаимодействие между процессами

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

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

Управление вводом-выводом и прерываниями

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

В [LIED96a] предлагается рассматривать аппаратное обеспечение как набор потоков, которые обладают уникальными идентификаторами и отправляют со­общения (содержащие только идентификатор данного потока) соответствующим программным потокам в пользовательском пространстве. Поток-получатель вы­ясняет, является ли данное сообщение прерыванием, а также определяет вид этого прерывания. Общая структура такого кода, выполняющегося на пользова­тельском уровне, имеет следующий вид:

driver thread;

do

waitFor (msg, sender);

if (sender== обрабатываемое_прерывание)

{

чтение/запись в порты ввода-вывода;

сброс аппаратного прерывания

}

else…

while (true);