Inferno OS Wiki
Регистрация
Advertisement

Роб Пайк, Дейв Пресотто, Шон Доруорд, Боб Фландрена, Кен Томпсон, Говард Трики, Фил Уинтерботтом

Bell Laboratories, Мюррей Хилл, Нью-Джерси 07974 США

Мотивация[]

К середине 80-х годов наметилась тенденция отхода от больших централизованных компьютеров, работающих в режиме разделения времени, и переориентации на сети из небольших персональных машин (как правило, из рабочих Unix-станций). Пользователям надоели вечно перегруженные «бюрократические» машины с разделением времени, и они стремились перейти на небольшие системы, которые могли обслуживать сами, даже если это влекло за собой потерю в вычислительной мощности. Микрокомпьютеры становились быстрее, и эти потери компенсировались. Такой стиль вычислений остается популярным и сегодня.

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

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

Проблемы ОС Unix были слишком глубоки, чтобы их можно было разрешить, однако некоторые ее особенности могли бы найти в дальнейшем свое применение. Это, в первую очередь, использование файловой системы для координирования именования ресурсов и доступа к ним, даже тех (например, устройств), интерпретация которых как файлов нетрадиционна. Для Plan 9 мы приняли эту идею, построив протокол сетевого уровня, названный 9Р, так, чтобы обеспечить машинам доступ к файлам на удаленных системах. Сверх того, была разработана система наименования, которая позволяет пользователям и их вычислительным агентам строить собственные представления ресурсов в сети. Именно здесь Plan 9 впервые начала отличаться от других операционных систем: ее пользователь строит личную вычислительную среду или заново создает ее тогда, когда пожелает, а не просто осуществляет все вычисления на личной машине. Вскоре стало ясно, что эта модель перспективнее, чем предполагалось, и идеи предварительной обработки пространства имен и трактовки ресурсов как файловой системы были распространены на всю ОС — на процессы, графику и даже на саму сеть.

К 1989 году система стала настолько устойчивой, что ее начали использовать в качестве единственной среды вычислений. Это означало необходимость перенесения многих служб и приложений, которые ранее применялись в ОС Unix. Мы использовали эту возможность, чтобы пересмотреть многие вопросы, связанные не только с резидентным ядром, которые Unix, как нам казалось, выполняла недостаточно хорошо. Plan 9 имеет новые компиляторы, языки, библиотеки, оконные системы и разнообразные новые приложения. Многие из старых инструментальных средств были опущены, а те, что оставлены, написаны заново или отлажены.

Почему было необходимо пересмотреть столь многое? Различия между операционной системой, библиотекой и приложением важны для исследователя операционных систем, но неинтересны для пользователей. Для них значение имеет только функциональность. Создавая полностью новую систему, мы смогли решить многие проблемы, которые, по нашему мнению, должны были быть решены. Например, в ядре реально отсутствует «драйвер tty», он является результатом работы оконной системы. В современном мире вычислительные системы в силу необходимости являются многоархитектурными и составлены из продуктов многих поставщиков, однако обычные компиляторы и инструментальные средства предполагают, что программа должна быть построена для работы в локальной среде. Важнее, однако, то, что определенным тестом для системы служит вычислительная среда, которую она предоставляет. Обеспечение большей эффективности при работе старых программ — «рабочих лошадок» Unix — было только делом техники; гораздо более мы были заинтересованы в том, чтобы новые идеи, предлагаемые архитектурой основополагающей системы, способствовали повышению эффективности работы. Таким образом, хотя Plan 9 обеспечивает среду эмуляции для выполнения команд POSIX, это не главное в системе. Большая часть системного ПО разработана в «родной» среде Plan 9.

Полностью обновленная система, безусловно, обладает определенными преимуществами. Во-первых, наша лаборатория имела опыт разработки контроллеров экспериментальных периферийных устройств. Для того чтобы облегчить написание их драйверов, мы хотели иметь систему, которая была бы доступна в исходной форме (чего уже не могла гарантировать Unix, даже в лаборатории, где она родилась). Кроме того, мы хотели перераспределить нашу работу: это означает, что ПО должно было создаваться децентрализованно. Например, мы могли бы использовать для нашей системы компиляторы С некоторых поставщиков, но, даже если бы мы преодолели проблемы с кросс-компиляцией, у нас возникли бы трудности с перераспределением результата этой работы.

Конструкция[]

Система построена на трех принципах. Во-первых, ресурсы именуются и к ним можно получить доступ как к файлам в иерархической файловой системе. Во-вторых, имеется стандартный протокол, называемый 9Р, для доступа к этим ресурсам. И, наконец, несвязанные иерархии, обеспечиваемые различными службами, соединяются вместе в единое личное иерархическое пространство имен файлов. Необычные свойства Plan 9 обусловлены целенаправленным последовательным применением этих принципов.

Крупная инсталляция Plan 9 состоит из ряда компьютеров, соединенных в сеть и предоставляющих каждый услуги определенного класса. Совместно используемые многопроцессорные серверы обеспечивают выполнение вычислительных циклов; другие большие машины служат хранилищами файлов. Эти машины расположены в помещении с кондиционированием воздуха и соединены высокопроизводительной сетью. Сети с меньшей пропускной способностью, такие как Ethernet или ISDN, соединяют эти серверы с офисными или домашними рабочими станциями или ПК, называемыми в терминологии Plan 9 терминалами. Рис. 1 показывает их размещение


Network

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

Локальные пространства имен предоставляют способ реализации представления сети «под себя». Все службы, доступные в сети, экспортируют иерархии файлов. Те из них, которые важны для пользователя, собираются вместе в личное пространство имен; не представляющие в данное время интереса игнорируются. Этот стиль использования отличается от «однородного глобального пространства имен». В Plan 9 имеются известные имена для служб и унифицированные имена для файлов, экспортированных этими службами, однако их представление полностью локально. Примером может служить разница между словосочетанием «мой дом» и четко сформулированным точным адресом. Последний может быть использован каждым, тогда как первое используется только в разговорной речи: смысл фразы меняется в зависимости от того, кто и когда ее произносит, однако она считается понятной. Подобным образом в Plan 9 имя /dev/mouse всегда относится к мыши, а /bin/date — это команда вывода даты, но то, какие файлы эти имена представляют, зависит от обстоятельств, например, от архитектуры машины, исполняющей команду date. Plan 9, таким образом, имеет локальные пространства имен, которые подчиняются глобальным соглашениям; именно эти соглашения гарантируют разумное поведение при наличии локальных имен.

Протокол 9Р структурирован как набор транзакций, каждая из которых посылает запрос от процесса клиента локальному или удаленному серверу и возвращает результат. 9Р контролирует файловую систему, а не только файлы; он включает процедуры для различения имен файлов и преобразования иерархии имен файловой системы, предоставляемой сервером. С другой стороны, в отличие от таких систем, как Sprite [7], пространство имен пользователя поддерживается только системой клиента, а не на сервере или с его помощью. Кроме того, доступ к файлам происходит на уровне байтов, а не блоков, что отличает 9Р от таких протоколов, как NFS и RFS. Дальнейшее сопоставление можно найти в работе [13].

Хотя Plan 9 изначально предназначалась для работы с традиционными файлами, ее идеи были распространены и на многие другие ресурсы. Службы Plan 9 по экспорту иерархий файлов включают устройства ввода/вывода, резервного копирования, оконную систему, сетевые интерфейсы и многое другое. Одним из примеров может быть команда файловой системы /proc, которая обеспечивает ясный способ исследования текущих процессов и управления ими. Прекурсорные системы имеют в основе подобную же идею [5], однако в Plan 9 метафора файлов развита много дальше [9]. Модель файловой системы хорошо понятна как разработчикам систем, так и обычным пользователям, так что службы, имеющие файлово-подобные интерфейсы легко построить, понять и использовать. Файлы поступают со знакомыми, унифицированными правилами защиты, наименования и доступа (как локального, так и удаленного), поэтому службы, построенные таким образом, готовы для использования в распределенных системах. (В этом заключается отличие от «объектно-ориентированных» моделей, где с этими аспектами приходится заново иметь дело для каждого класса объектов.) В последующих разделах приведены примеры, иллюстрирующие эти идеи на практике.

Представление на командном уровне[]

Plan 9 предназначена для использования на машинах с дисплеем и функционирующей оконной системой. Она не имеет представления о «телетайпе» в том смысле, какой присущ Unix. Работа с клавиатурой в основной системе находится на рудиментарном уровне, однако при функционировании оконной системы 8½ [8] текст можно редактировать с помощью операций «вырезать и вклеить» из всплывающих меню, копировать между окнами и т.д. 8½ позволяет редактировать текст в предыдущей, а не только в текущей строке. Редакторские возможности достаточно мощны для перемещения таких специальных функций, как история, в оболочку, для разбивки на страницы и прокрутки и редактирования почты. Окна 8½ не поддерживают адресацию курсора и, кроме одного терминального эмулятора для упрощения связи с традиционными системами, в Plan 9 отсутствует ПО для адресации курсора.

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

Окна создаются работающей программой, например, оболочкой, со стандартными входом и выходом, связанной с редактируемым текстом окна. Каждое окно имеет также личное побитовое отображение и мультиплексированный доступ к клавиатуре, мыши и другим графическим ресурсам через файлы типа /dev/mouse, /dev/bitblt и /dev/cons (аналогично /dev/tty в Unix). Эти файлы предоставляются редактором 8½, выступающим в роли файлового сервера. В отличие от системы Х Window, где новое приложение обычно создает новое окно, в котором и исполняется, графическое приложение 8½ обычно выполняется в том окне, где стартует. Возможным и эффективным для приложения является создание нового окна, но это не в стиле системы. В отличие от Х Window, где удаленное приложение для начала выполнения делает сетевой вызов Х-серверу, удаленное приложение 8½ видит файлы mouse, bitblt и cons для окна как обычно в /dev. Оно не знает, локальные ли это файлы, а просто читает и записывает их для управления окном; сетевая связь уже присутствует и мультиплексируется.

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

Набор команд Plan 9 подобен таковому у Unix. Команды разделяются на несколько обширных классов. Некоторые из них представляют собой новые программы для выполнения старой работы: программы, подобные ls, cat и другим, имеют знакомые имена и функции, но это новые, более простые их версии. Команда who, например, является командным файлом, а ps — просто 95 строк кода С. Некоторые команды с необходимостью совпадают с их предшественниками в Unix awk, troff и другие были конвертированы в ANSI С и расширены для обработки Unicode, но все еще представляют собой знакомые инструменты. Другие команды — полностью новые программы, заполняющие старые ниши: командный интерпретатор rc, текстовый редактор sam, отладчик acid и другие заменяют хорошо известные инструменты Unix, выполняя подобные же функции. Наконец, около половины команд совсем новые.

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

Файловый сервер[]

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

У файлового сервера три уровня хранения. Центральный сервер в нашей инсталляции имеет буферную память объемом около 100 MB, магнитный диск емкостью 27 GB и дисковод с автоматической сменой WORM-дисков общей емкостью 350 GB как основной накопитель. Магнитный диск — не что иное как кеш-память для WORM-дисковода, а буферная память — кеш для диска; каждый уровень намного быстрее и видит трафик примерно на порядок больший, чем уровень, который он кеширует. Объем адресуемых данных в файловой системе может быть больше, чем объем магнитных дисков, поскольку они являются только кешем; наш главный файловый сервер имеет около 40 GB активного объема хранения.

Наиболее необычная черта файлового сервера обусловлена использованием WORM-устройства для постоянного хранения. Каждое утро в 5 часов автоматически происходит дамп файловой системы. Система замораживается, и все блоки, модифицированные со времени последнего дампа, становятся в очередь для записи на WORM. После этого служба восстанавливается, и в иерархии всех дампов, когда-либо проведенных, появляется корневой каталог выведенной файловой системы с атрибутом «только для чтения», названный по дате создания. Например, каталог /n/dump/1995/0315 — корневой для образа файловой системы в том виде, каком он был на раннее утро 15 марта 1995 года. Создание очереди из блоков занимает несколько минут, однако процесс копирования блоков на WORM, который происходит в фоновом режиме, может занять часы.

Возможны два способа использования дампа файловой системы. Во-первых, сами пользователи могут непосредственно просматривать дамп или присоединять его участки к своему пространству имен. Например, чтобы выявить причину ошибки, естественно попробовать откомпилировать программу из ее состояния три месяца назад или связать программу со вчерашней библиотекой. Имея ежедневную картину всех файлов, легко обнаружить, когда было сделано конкретное изменение или какие изменения были сделаны в конкретный день. Рискуя делать большие изменения в файлах, пользователи чувствуют себя более свободно, сознавая, что они могут вернуться назад с помощью одной команды копирования. Система собственно резервного копирования отсутствует; вместо нее, имея в арсенале дамп в пространстве имен файлов, проблемы резервного копирования можно разрешить с помощью стандартных инструментальных средств, такие как команды ср, ls, grep и diff.

Другое (очень редкое) использование — это резервное копирование всей системы. В случае повреждения, активная файловая система может быть инициализирована из любого дампа очисткой дискового кеша и введением установки, чтобы корневой каталог активной файловой системы был копией корневого каталога дампа. Но не надо думать, что все так просто: кроме потерь всех изменений, сделанных после даты дампа, этот метод восстановления приводит к очень медленной работе системы. Кеш должен быть перезагружен из WORM, который намного медленнее, чем магнитные диски. Файловой системе потребуется несколько дней, чтобы перезагрузить рабочий набор и восстановить полную производительность.

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

После того, как файл записан на WORM-диски, он не может быть перемещен, поэтому наши пользователи никогда не видят сообщения «сотрите, пожалуйста, ваши файлы», и в системе отсутствует команда df. Мы считаем дисковод WORM неограниченным ресурсом. Единственный вопрос заключается в том, сколько времени потребуется на его заполнение. Наш накопитель WORM служил сообществу из почти 50 пользователей в течение 5 лет и поглотил ежедневные дампы, заполнив 65 % своей емкости. Сейчас его производитель улучшил технологию, удвоив емкость отдельных дисков. Если бы мы перешли на новую среду, мы могли бы иметь больше свободного пространства, чем исходный пустой накопитель. В результате развития технологии емкость систем хранения растет быстрее, чем мы можем ее использовать.

Необычные файловые серверы[]

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

Возможно, наиболее заметным файловым сервером в Plan 9 можно назвать оконную систему 8½. Она уже рассматривалась подробно [8], но стоит привести здесь ее краткое описание. 8½ обеспечивает два интерфейса: пользователю, сидящему перед терминалом, она предлагает взаимодействие в традиционном стиле с множеством управляемых с помощью мыши и клавиатуры окон, в каждом из которых выполняется приложение. Для клиентских программ вид также достаточно традиционен: программы, выполняющиеся в окне, видят набор файлов в /dev с именами типа mouse, screen и пр. Программы, которым необходимо напечатать текст в своем окне, производят запись в /dev/cons; чтобы обратиться к мыши, они считывают /dev/mouse. В стиле Plan 9 побитовая графика применятся обращением к файлу /dev/bitblt, куда клиенты записывают кодированные сообщения для исполнения таких графических операций, как bitblt (RasterOp). Необычно то, как это делается: 8½ является файловым сервером, предоставляющим файлы из каталога /dev клиентам, работающим в каждом окне. Хотя каждое из окон выглядит для ее клиентов одинаково, все они имеют отдельные наборы файлов в /dev. 8½ мультиплексирует доступ своих клиентов к ресурсам терминала путем обслуживания множества наборов файлов. Каждому клиенту предоставляется личное пространство имен с различным набором файлов, которые одинаково работают и во всех других окнах. Такая структура имеет много преимуществ. Одно из них заключается в том, что 8½ обслуживает те же файлы, которые необходимы для его собственного внедрения (он мультиплексирует свой собственный интерфейс), и поэтому может работать рекурсивно, как клиент самого себя. Кроме того, рассмотрим внедрение /dev/tty в Unix, требующее специального кода в ядре для перенаправления вызовов open соответствующим устройствам. Вместо этого в 8½ эквивалентная служба выпадает автоматически: 8½ обслуживает /dev/cons как свою основную функцию; ничего другого он не делает. Когда программа хочет считать с клавиатуры, она открывает /dev/cons, но это личный файл, а не совместно используемый со специальными свойствами. Снова это становится возможным из-за локальности пространства имен; соглашения о совместимости файлов делают эту возможность легко осуществимой.

8½ имеет уникальную особенность, вытекающую из ее строения. Реализуясь как файловый сервер, он обладает возможностью отложенного ответа на запросы чтения для конкретного окна. Эта опция переключается зарезервированной клавишей клавиатуры. Нажав ее один раз, вы приостановите чтение клиента из окна; повторное нажатие восстанавливает нормальное чтение, которое построчно поглощает любой текст. Таким образом, пользователь сможет редактировать многострочный входной текст на экране до того, как приложение видит его; устраняется необходимость включения отдельного редактора для подготовки текста, например, почтовых сообщений. С этим связана и возможность ответа на считывания непосредственно из структуры данных, определяющих текст на дисплее: текст можно редактировать до тех пор, пока его конечная новая строка делает подготовленную строку текста считываемой для клиента. Даже в то время, когда строка считывается, текст, который увидит клиент, может быть изменен. Например, после набора в оболочке, пользователь может вернуться назад на конечную новую строку в любое время, пока не кончится работа make и не появится следующее приглашение оболочки перед rm. Пользователь может прервать выполнение команды rm или даже указать мышью до rm и набрать другую команду, чтобы она исполнялась первой.

В Plan 9 отсутствует команда ftp. Вместо нее файловый сервер на уровне пользователя генерирует вызовы ftpfs к узлу FTP, входит в него от имени пользователя и использует протокол FTP для исследования файлов в удаленном каталоге. Для локального пользователя он предлагает иерархию файлов, присоединенных к /n/ftp в локальном пространстве имен, отражая содержание узла FTP. Такая реализация рискованна: для эффективности ftpfs придется делать некоторый усложненный захват с использованием эвристического подхода для декодирования информации удаленного каталога. Однако результат стоит того: все локальные средства управления файлами, такие как ср, grep, diff и, конечно, ls, доступны для обслуживаемых FTP-файлов точно так же, как если бы они были локальными файлами. Другие системы, например Jade and Prospero, используют ту же возможность[6; 11].

Один сервер, exportfs, является процессом пользователя, занимающим часть его собственного пространства имен и делающим его доступным для других процессов путем трансляции запросов 9Р в системные вызовы ядра Plan 9. Иерархия файлов, которую он экспортирует, может содержать файлы из множества серверов. Exportfs обычно исполняется как удаленный сервер, инициируемый локальной программой, или import, или cpu. Import производит сетевой вызов удаленной машины, затем стартует exportfs и подсоединяется к локальному пространству имен. Например, команда

import helix /net

делает интерфейс сети Helix видимым в локальной директории /proc, позволяя локальным отладчикам исследовать удаленные процессы.

Команда cpu подключает локальный терминал к удаленному серверу CPU. Она работает в направлении, обратном команде import после вызова сервера, она запускает локальную exportfs и встраивает ее в пространство имен процесса на сервере, обычно через вновь создаваемую оболочку. Затем она перекомпонует пространство имен, чтобы сделать локальные файлы устройства (как те, которые обслуживаются оконной системой терминала) видимыми в каталоге сервера /dev. Эффект действия команды cpu сводится, следовательно, к запуску оболочки на быстрой машине с пространством имен, аналогичном локальному, при наличии еще одной, тесно связанной с файловым сервером. Все локальные файлы устройств видимы с удаленной машины, так что удаленные приложения имеют полный доступ к локальным службам, таким как растровая графика, /dev/cons и т. д. Это не то же, что rlogin, которая не делает ничего для воспроизводства локального пространства имен на удаленной системе, и не то же, что совместное использование файлов при работе, например, с NFS, при котором можно достичь некоторой эквивалентности пространства имен, но не такой же комбинации доступа к локальным аппаратным устройствам, удаленным файлам и удаленным ресурсам вычислительного сервера. Команда cpu является уникальным прозрачным механизмом. Например, разумно запустить систему окон в окне с работающей командой cpu; все окна, созданные в нем, автоматически запускают процесс на вычислительном сервере.

Конфигурируемость и управление[]

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

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

Центральные файловые серверы централизуют не только файлы, но и их администрирование и обслуживание. В действительности один сервер является главным, содержащим все системные файлы; другие серверы обеспечивают дополнительное место для хранения или доступны для отлаживания и другого специального использования, однако системное ПО размещено на одной машине. Это означает, что каждая программа имеет единственную копию двоичного кода для каждой архитектуры, так что инсталляция новых версий и поиск ошибок достаточно тривиальны. Имеется также единственная база данных пользователя; нет необходимости синхронизировать отдельные файлы /etc/passwd. С другой стороны, зависимость от единого центрального сервера не ограничивает размер инсталляции и непрерывность сервиса. Хотя центральный сервер обычно остается включенным в течение месяцев, когда он выключен, зависящие от него машины не могут функционировать.

Другим примером мощи централизованной файловой службы является то, как Plan 9 управляет сетевой информацией. На центральном сервере существует директория /lib/ndb, которая содержит всю информацию, необходимую для управления локальной сетью Ethernet и другими сетями. Все машины используют для обращения к сети одну и ту же базу данных; нет необходимости управлять распределенной системой наименований или сохранять параллельные файлы до последнего момента. Чтобы инсталлировать новую машину в локальную сеть Ethernet, надо выбрать имя и IP-адрес и добавить их к единственному файлу в /lib/ndb; все машины в инсталляции смогут обратиться к ней сразу же. Чтобы начать работу, подсоедините машину к сети, включите ее и используйте ВООТР и TFTP для загрузки ядра. Все остальное произойдет автоматически.

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

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

Программирование на С[]

Утилиты Plan 9 написаны на нескольких языках. Некоторые из них представляют собой сценарии оболочки rc [2], многие написаны на новом языке-конкуренте, подобном С, названном Alef и описанном ниже. Большая же часть написана на диалекте ANSI С. Из них большинство являются полностью новыми программами, однако происхождение некоторых идет от Unix-кода, предшественника ANSI С. Эти части были обновлены до ANSI С и переработаны для большей мобильности и чистоты.

Диалект Plan 9 имеет некоторые небольшие добавления, описанные ранее [10], и несколько основных ограничений. Наиболее важные из них — это требование компилятора, чтобы все определения функций имели прототипы ANSI и все вызовы функций появлялись в контексте прототипной декларации функций. Как стилистическое правило, прототипная декларация помещена в файл заголовка, включенный во все файлы, которые вызывают функцию. Каждая системная библиотека имеет ассоциированный файл заголовка, декларирующий все функции в этой библиотеке. Например, стандартная библиотека Plan 9 называется libc, так что все файлы-источники включают <libc.h>. (Имена файлов заголовка не соответствуют ANSI С.) Эти правила гарантируют, что все функции вызываются с аргументами, имеющими ожидаемые типы, что не было свойственно программам на языке, предшествующем ANSI С.

Другое ограничение заключается в том, что для компиляторов С приемлем только поднабор препроцессорных директив, требуемых ANSI. Основное опущенное звено — #if, поскольку мы считаем, что оно никогда не было необходимым и часто использовалось неправильно. Кроме того, его эффект лучше достигался другими средствами. Например, #if, используемый для переключения характеристик во время компиляции, может быть переписан как обычный оператор if, основанный на свертке с константой времени компилирования и исключении мертвого кода для отбрасывания объектного кода.

Условная компиляция, даже с #ifdef, в Plan 9 используется как резервная. Единственные зависимые от архитектуры операторы #ifdef в системе находятся в процедурах низкого уровня в графической библиотеке. Мы избегали таких зависимостей или, когда это было необходимо, выделяли их в отдельные файлы-источники или библиотеки. Кроме того, что применение #ifdef делает код трудночитаемым, становится невозможным узнать, какой источник скомпилирован в двоичный вид или будет ли источник, защищенный ими, компилироваться или работать правильно. Они также затрудняют поддержку ПО.

Стандартная библиотека Plan 9 перекрывается во многом с ANSI С и POSIX, но расходится с ними при адаптации к целям или реализации Plan 9. Когда изменялась семантика функции, мы изменяли также и имя. Например, вместо оператора Unix create, Plan 9 имеет функцию create, которая воспринимает три аргумента — два исходных, плюс третий, который, подобно второму аргументу open, определяет, должен ли возвращенный дескриптор файла быть открыт для чтения, записи или того и другого. Такой подход был вынужденным из-за способа, которым 9Р выполняет создание, однако он упрощает также общее использование create для инициализации временного файла.

Другое отступление от ANSI С заключалось в том, что Plan 9 использует 16-разрядный набор символов, называемый Unicode. Хотя мы совершенно прекратили полную интернационализацию, Plan 9 обрабатывает представление всех основных языков однородно по всему своему ПО. Для упрощения обмена текстами между программами, символы скомпонованы в поток битов путем сконструированной нами процедуры кодировки, названной UTF-8, которая в настоящее время начинает приниматься в качестве стандартной. Она имеет несколько привлекательных свойств, включая независимость от порядка байт, обратную совместимость с ASCII и легкость внедрения.

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

Небольшой класс программ Plan 9 не следует соглашениям, обозначенным в этом разделе. Это программы, импортированные из сообщества Unix или им поддерживаемые; представительным их примером является TeX. Чтобы избежать многократного конвертирования таких программ всякий раз, когда выпускается новая версия, мы создали переносимую среду, названную ANSI C/POSIX Environment (АРЕ) [13]. АРЕ включает отдельные файлы, библиотеки и команды, соответствующие насколько можно более точно спецификациям ANSI С и базового POSIX. Для возможности переносимости сетевого ПО, такого как Х Window, к этим спецификациям было необходимо добавить некоторые дополнения, такие как сетевые функции BSD.

Переносимость и компиляция[]

Plan 9 переносима на множество процессорных архитектур. В рамках одного сеанса расчетов, общим правилом является использование нескольких архитектур. Возможна оконная система, работающая на процессорах Intel, соединенных с вычислительным сервером на основе MIPS с файлами, размещенными на системе SPARC. Для прозрачности такой разнородной системы должны существовать соглашения относительно обмена данными между программами; чтобы поддержка ПО была прямой, должны быть соглашения о кросс-платформной компиляции.

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

Программы, включая ядро, часто представляют свои данные через интерфейс файловой системы — механизм доступа, который изначально переносим. Например, библиотечная функция time (системный вызов time отсутствует) читает файл и конвертирует его в двоичный. Подобным же образом, вместо кодирования состояния прикладного процесса в серии флагов и битов в персональной памяти, ядро представляет текстовую последовательность в файле, называемом status в файловой системе /proc, ассоциированной с каждым процессом. Команда Plan 9 ps тривиальна: она распечатывает содержимое файлов статуса после некоторого небольшого переформатирования; более того, после команды

import helix /proc

локальная команда ps выдает отчет о состоянии процессов Helix.

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

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

Поскольку Plan 9 работает на множестве архитектур, даже одиночная инсталляция, различающая имена компиляторов и промежуточных файлов, упрощает многоархитектурную разработку из единого дерева-источника. Компиляторы и загрузчики для каждой архитектуры имеют уникальные имена; команда сс отсутствует. Имена получаются путем конкатенации символа кода, ассоциированного с конечной архитектурой, с именем компилятора или загрузчика. Например, символ кода для процессоров Intel x86 — «8», соответствующий компилятор С назван 8с, компилятор Alef — 8al, а загрузчик — 8l. Подобным же образом, промежуточные файлы имеют суффиксы .8, а не .о.

Программа Plan 9 mk, родственная make, читает имена текущей и конечной архитектур из переменных окружения, названных 8cputype и $objtype. По умолчанию, текущий процессор является целевым, однако подстановка $objtype в имя другой архитектуры перед вызовом mk приводит к кросс-созданию:

objtype=sparc mk создает программу для архитектуры SPARC независимо от исполняющей машины. Значение $objtype выбирает файл зависящих от архитектуры определений переменных, который конфигурирует создание для использования соответствующих компиляторов и загрузчика. Эта методика, хотя и простая по идее, хорошо работает и на практике: все приложения в Plan 9 созданы из единого дерева-источника и возможно создание различных параллельных архитектур без конфликтов.

Параллельное программирование[]

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

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

Основные требования параллельных программ таковы: управление разделяемыми ресурсами; наличие интерфейса к планировщику; детализированная синхронизация с использованием взаимоблокировок. У команды rfork предусмотрен аргумент, битовый вектор, устанавливающий, какие из ресурсов родительского процесса должны быть использованы совместно, скопированы или созданы заново в дочернем процессе. К числу этих ресурсов относятся: пространство имен, окружение, таблица дескрипторов файлов, память и пометки (аналог механизма сигналов Unix). Один из бит определяет, действительно ли rfork создаст новый процесс: если бит выключен, дальнейшая модификация ресурсов будет выполняться в том же процессе, который выполнил вызов. Alef поддерживает ветвление, в котором все ресурсы, включая память, совместно используются родительским и порожденным процессами, по аналогии с порождением нитей во многих системах.

Доказательством правильности модели rfork является множество способов, какими она используется. В отличие от канонического использования fork, трудно найти два обращения к rfork с одинаковым набором бит. Система с двумя типами процессов — обычными и нитями — не была бы столь гибкой.

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

Системный вызов rendezvous обеспечивает синхронизацию процессов. Alef использует его для организации коммуникационных каналов, блокировок создания очередей, множественных блокировок «чтение/запись» и механизма перевода в состояние ожидания и активизации. У rendezvous два аргумента, тэг и значение. Вызов rendezvous с некоторым тэгом переводит процесс в состояние ожидания, до тех пор пока другой процесс не представит соответствующий тэг. Когда между тэгами в паре имеется соответствие, происходит обмен их значениями между двумя процессами и оба вызова возвращают управление. Эта примитивная схема достаточна для построения полного набора средств синхронизации.

Взаимоблокировки обеспечиваются архитектурно-зависимой библиотекой, доступной пользователю. Большинство процессоров снабжены набором инструкций, которые могут использоваться для введения блокировок на «атомарном уровне». Исключением является MIPS R3000: процессоры семейства SGI Power Series имеют специальную аппаратную блокировку на шине.

Независимо от «веса», процесс Plan 9 будет блокироваться. Это означает, что, когда программа хочет считать из медленного устройства без блокировки всех вычислений, она должна разветвить процесс, чтобы сделать для него чтение. Решение заключается в том, чтобы начать сопутствующий процесс, который произведет ввод/вывод и выдаст результат в основной процесс путем совместно используемой памяти или, возможно, конвейера. Это звучит тяжеловато, но на практике работает легко и эффективно; в действительности, большинство интерактивных приложений Plan 9, даже относительно обычных, написанных на С, таких как текстовый редактор sam, исполняются как многопроцессные программы.

Поддержка ядром параллельного программирования в Plan 9 заключена в нескольких сотнях строк переносимого кода; куча простых примитивов позволяет отслеживать проблемы на уровне пользователя. Хотя эти C-примитивы и работают хорошо, создание и управление подчиненными процессами куда проще запрограммировать на Alef. Высокоуровневая поддержка параллельного программирования на языке уровня пользователя, а не в ядре способствует согласованности интерфейсов между всеми компонентами. Сравните такой подход с системным вызовом select в Unix: select применим только к ограниченному набору устройств, не может быть обобщен на сетевые задачи, труден в использовании.

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

Реализация пространств имен[]

Пространство имен организуется при помощи трех вызовов: mount, bind и unmount. Вызов mount присоединяет дерево, обслуживаемое файловым сервером, к текущему пространству имен, расширяя его; bind копирует часть существующего пространства имен в другую точку в пространстве имен; unmount отменяет действие mount или bind.

При использовании вызовов bind или mount, в одной точке пространства имен может быть организован стек из нескольких каталогов. В терминологии Plan 9 это называется объединенным каталогом, который ведет себя подобно конкатенации составляющих его каталогов. Специальный аргумент bind и mount устанавливает положение нового каталога в объединении, допуская добавление новых элементов в начало или конец объединения, причем каждый его элемент ищется поочередно и берется первый подходящий. Объединенные каталоги являются одним из наиболее широко используемых свойств организации пространства имен Plan 9. Например, каталог /bin построен как объединение каталогов /$cputype/bin (двоичные коды), /rc/bin (командные файлы) и, возможно, других, включенных пользователем. Это устраняет необходимость в переменной окружения PATH.

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

Универсальный протокол 9Р объединяет компоненты Plan 9, образуя распределенную систему. Вместо изобретения уникального протокола для каждой службы, такого как rlogin, FTP, TFTP и X Window, Plan 9 реализует службы как операции над файловыми объектами и затем использует единый, хорошо документированный протокол для обмена информацией между компьютерами.

Будучи внешне похожим на NFS, 9Р, однако, воспринимает файлы как последовательность байт, а не блоков. Кроме того, в отличие от NFS, клиенты выполняют вызовы удаленных процедур для установки указателей на объекты в удаленном файловом сервере. Эти указатели называются файловыми идентификаторами, которые используются для идентификации объекта в удаленной файловой системе.

Протокол 9Р определяет 17 сообщений, обеспечивающих средства для аутентификации пользователей, навигации по иерархии файловой системы, копирования файлов, выполнения ввода/вывода, изменения атрибутов файлов и их создания и удаления. Процедура для получения доступа к иерархии имен, предоставляемой сервером, такова. Связь с файловым сервером устанавливается через конвейер или сетевое соединение. Начальное сообщение session выполняет двустороннюю аутентификацию между клиентом и сервером. Сообщение attach затем подсоединяет файловый идентификатор, предлагаемый системой клиента, к корневому каталогу дерева файлов сервера. Одновременно с этим проверяется идентичность пользователя. Соединение могут разделять несколько пользователей, однако каждый должен выполнять операцию подсоединения, чтобы установить свою идентичность.

Сообщение walk перемещает файловый идентификатор через один уровень иерархии файловой системы. Сообщение clone порождает копию идентификатора, которая указывает на тот же файл как на оригинал. Цель этого шага — переход к файлу в каталоге без потери указателя на сам каталог. Сообщение open блокирует идентификатор некоторого файла, проверяет разрешения на доступ и подготавливает его к вводу/выводу. Сообщения read и write выполняют операции ввода/вывода. Сообщение clunk указывает, что клиент не может больше использовать идентификатор. Сообщение remove приводит к удалению файла и перераспределению ресурсов сервера должен быть распределен заново.

Протокол 9Р имеет две формы: сообщения RPC, посылаемые по конвейеру или сетевому соединению, и процедурный интерфейс внутри ядра. Поскольку драйверы устройств помещены в ядро, они адресуемы непосредственно, и для связи с ними нет необходимости посылать сообщения; вместо этого каждое действие 9Р выполняется путем прямого вызова процедуры. Такое раздвоение дает, по меньшей мере, пару преимуществ. Первое — повышенная скорость адресации локальных устройств. Второе — возможность обойтись одной реализацией RPC: системный механизм вызова удаленной процедуры объединен с мультиплексированием сообщений 9Р в единый компонент.

Для каждого идентификатора файла ядро поддерживает его локальное представление в структуре данных, называемое каналом (channel), так что все операции над файлами, выполняемые ядром, включают канал, соединенный с этим идентификатором. Простейший пример: дескрипторы файлов процесса пользователя, отображаемые в набор каналов. Таблица в ядре представляет список, имеющийся для каждого устройства, точек входа, соответствующих сообщениям 9Р. Системный вызов (например read) переводится в один или больше вызовов процедур согласно этой таблице, индексированных по типу, сохраняемому в канале: procread, eiaread и т.д. Специальное устройство монтирования ядра (mount device) позволяет перевести вызовы процедур в сообщения, то есть конвертирует локальные вызовы процедур в удаленные. В сущности, этот специальный драйвер становится локальным замещением для файлов, обслуживаемых удаленным файловым сервером. Указатель канала в локальном вызове переводится в ассоциированный файл в переданном сообщении.

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

Каждый файл в Plan 9 однозначно идентифицируется набором целых чисел: типом сервера (сохраняемого в канале и используемого как индекс в таблице вызовов функций), номером сервера или устройства, различающего сервер от других такого же типа (разрешимый локально драйвером), и идентификатором, образованный двумя 32-разрядными числами, называемыми путем (path) и версией (version). Путь является уникальным номером файла, присвоенным драйвером устройства или файловым сервером при создании файла. Номер версии обновляется при модификации файла; он может быть использован для поддержания когерентности кеша между клиентами серверами.

Тип и номер устройства аналогичны большому и малому номерам устройства в Unix; комбинация путь-версия аналогична идентификатору i-number. Устройство и тип связывают канал с драйвером устройства, а путь-версия идентифицирует файл в пределах этого устройства.

Cообщения протокола 9Р
Сообщение 9Р Описание
Nop Нет операции; используется для отладки.
Session Установить соединение.
Attach Проверить пользователя и присоединить идентификатор к корневому каталогу.
Clone Дублировать идентификатор файла.
Walk Продвинуть идентификатор на один уровень в иерархии каталогов.
Open Проверить разрешения на доступ и разрешить чтение и запись.
Create Создать новый файл (или каталог).
Read Считать содержимое файла, ассоциированного с идентификатором.
Write Записать содержимое файла, ассоциированного с идентификатором.
Clunk Освободить идентификатор.
Remote Удалить файл, ассоциированный с идентификатором.
Stat Считать свойства файла, ассоциированного с идентификатором.
Wstat Модифицировать свойства файла, ассоциированного с идентификатором.
Flush Сбросить выведенное сообщение 9Р.
Error (Только ответ) Возвратить сообщение об ошибке из неудачного вызова.
Clwalk Используется только специальными серверами по низкоскоростным линиям.

Кеширование файлов[]

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

Поле версий при модификации файла изменяется слабо, что делает возможным осуществление некоторых слабо когерентных форм кеширования. Наиболее важной из них является кеширование сегментов текста и данных исполняемых файлов на клиенте. Когда процесс выполняет вызов exec, файл открывается заново и поле версии сравнивается с версией в кеше; если они соответствуют друг другу, используется локальная копия. Такой же метод может быть использован для организации локального кеширующего файлового сервера. Этот сервер уровня пользователя является посредником в соединениях 9Р с удаленным сервером и отслеживает трафик, копируя данные на локальный диск. Когда он встречает команду чтения известных данных, он отвечает непосредственно, тогда как записи проходят немедленно (кеш со сквозной записью), чтобы центральная копия всегда была обновленной. Эта процедура прозрачна для процессов на терминале и не требует изменений для 9Р; он работает хорошо и на домашних машинах, соединенных последовательными линиями. Подобный метод может быть также использован и для организации общего клиентского кеша в неиспользуемой локальной памяти, однако в Plan 9 этого сделано не было.

Сети и коммуникационные устройства[]

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

Следующий пример иллюстрирует структуру TCP устройства:

% ls -lp /net/tcp
d-r-xr-xr-x I 0 bootes bootes 0 Feb 23 20:20 0
d-r-xr-xr-x I 0 bootes bootes 0 Feb 23 20:20 1
--rw-rw-rw- I 0 bootes bootes 0 Feb 23 20:20 clone
% ls -lp /net/tcp/0
--rw-rw---- I 0 rob bootes 0 % ls -lp /net/tcp
d-r-xr-xr-x I 0 bootes bootes 0 Feb 23 20:20 0
d-r-xr-xr-x I 0 bootes bootes 0 Feb 23 20:20 1
--rw-rw-rw- I 0 bootes bootes 0 Feb 23 20:20 clone
% ls -lp /net/tcp/0
--rw-rw---- I 0 rob bootes 0 Feb 23 20:20 ctl
--rw-rw---- I 0 rob bootes 0 Feb 23 20:20 data
--rw-rw---- I 0 rob bootes 0 Feb 23 20:20 listen
--r--r--r-- I 0 bootes bootes 0 Feb 23 20:20 local
--r--r--r-- I 0 bootes bootes 0 Feb 23 20:20 remote
--r--r--r-- I 0 bootes bootes 0 Feb 23 20:20 status
%



Верхний каталог /net/tcp содержит файл clone и ряд последовательно пронумерованных подкаталогов. Каждый подкаталог соответствует IP-соединению. Открытие clone резервирует неиспользованное соединение и открывает его управляющий файл. Чтение управляющего файла возвращает номер соединения в текстовой форме, так что процесс пользователя может построить полное имя вновь назначенного каталога соединения. Файлы local, remote и status являются диагностическими: например, remote содержит адрес (для ТСР/IP — адрес и номер порта) удаленного узла. Вызов инициируется записью сообщения о соединении с конкретным сетевым адресом в качестве его аргумента; например, чтобы открыть сеанс Telnet (порт 23) с удаленной машиной с IP-адресом 135.104.9.52, последовательность должна быть такой:

connect 135.104.9.52!23

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

announce 23

в свой управляющий файл, чтобы указать свою готовность к получению вызовов на этот порт. В Plan 9 такой демон называется слушатель (listener).

Однородная структура для сетевых устройств не может скрыть все детали адресации и коммуникации для различающихся сетей. Например, Datakit использует текстуальные иерархические адреса, отличающиеся от 32-разрядных адресов IP, так что определенный приложением управляющий файл должен все же знать, какую сеть он представляет. Вместо того, чтобы каждое приложение знало адресацию каждой сети, Plan 9 скрывает эти детали в сервере соединений (connection server), называемом cs. Cs — это файловая система, смонтированная в известном месте. Этот механизм позволяет приложению установить соединение с хостом. Приложение передает символьный адрес и имя службы, например net!kremvax!telnet, и получает в ответ имя открываемого файла и представляемый ему адрес, например /net/tcp/clone 111.123.112.94!23. Если машины связаны несколькими сетями, cs представляет список возможных сетей и адресов, которые будут последовательно перебираться; порядок определяется эвристически. Например, первым представляется вариант с наибольшей пропускной способностью.

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

Благодаря однородной структуре сетей в Plan 9 для организации сетей достаточно команды import.

Поддержка сетей на уровне ядра[]

В ядре для построения коммуникационных каналов Plan 9 предусмотрен специальный механизм, называемый потоками (streams). Поток — это двунаправленный канал, соединяющий физическое или псевдоустройство с процессом пользователя. Процесс пользователя вводит и удаляет данные на одном конце потока; процесс ядра, действующий от имени устройства, выполняется на другом конце. Поток включает линейный список обрабатывающих модулей (processing modules). Каждый модуль обладает процедурой продвижения данных как вверх (к процессу), так и вниз (к устройству). Вызов этой процедуры модуля на любом конце потока вводит в него данные. Каждый модуль вызывает последующий для посылки данных вверх или вниз по потоку. Подобно потокам Unix, потоки Plan 9 могут быть сконфигурированы динамически.

Протокол IL[]

Протокол 9Р должен выполняться поверх надежного транспортного протокола. 9Р не имеет механизма для восстановления после ошибок передачи, и система предполагает, что каждое считывание из коммуникационного канала возвратит единственное сообщение 9Р; она не анализирует поток данных для определения границ сообщений. Конвейеры и некоторые сетевые протоколы уже имеют эти возможности, но стандартный протокол 9Р — нет. TCP не разделяет сообщения, тогда как UDP не обеспечивает надежной упорядоченной доставки.

Мы разработали новый протокол, названный IL (Internet Link), для передачи сообщений 9Р поверх IP. Это основанный на предварительном соединении протокол, обеспечивающий надежную передачу упорядоченных сообщений между машинами. Так как процесс может иметь только один ожидающий выполнения запрос 9Р, в IL нет необходимости в управлении потоком. Подобно ТСР, в IL предусмотрены адаптивные задержки: он изменяет времена квитирования и ретрансляции, согласуя их с пропускной способностью сети. Это позволяет протоколу хорошо работать в сетях как Internet, так и в локальных Ethernet. Кроме того, IL не затемняет повторную передачу, чтобы не вызвать дополнительной перегрузки сети.

В Plan 9 использование IL меньше и быстрее, чем ТСР. IL является нашим основным транспортным протоколом Internet.

Аутентификация[]

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

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

Процесс аутентификации двусторонний: в конце аутентификационного обмена каждая сторона приобретает убежденность в идентичности другой. Каждая машина начинает обмен, имея в памяти ключ DES. В случае вычислительных и файловых серверов ключ, имя пользователя и имя домена для сервера считываются из постоянной памяти. В случае терминалов ключ порождается из пароля, набираемого пользователем во время загрузки. Специальный компьютер, известный как сервер аутентификации (authentication server), поддерживает базу данных ключей для всех пользователей в своем административном домене и участвует в процедуре аутентификации.

Процедура аутентификации в чем-то подобна системе Kerberos, но в отличие от нее не завязана на синхронизацию часов. Кроме того, в отличие от Kerberos, аутентификация Plan 9 поддерживает связь типа «говорить за», которая позволяет одному пользователю получать полномочия другого; именно таким образом вычислительный сервер выполняет процессы от имени своих клиентов.

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

Аутентификация внешних соединений[]

Обычный протокол аутентификации Plan 9 не подходит для текстовых служб, таких как Telnet или FTP. В этих случаях пользователи Plan 9 проходят аутентификацию с помощью DES-калькулятора (используется продукт SecureNet Key компании Digital Pathways). Аутентификатор содержит ключ, отличный от обычного ключа пользователя. Пользователь идентифицируется аутентификатором по четырехзначному значению PIN (индивидуального идентификационного номера). Правильный PIN позволяет аутентификатору обмениваться вызовом/ответом с сервером. Поскольку правильный обмен действителен только один раз и ключи никогда не посылаются по сети, эта процедура не чувствительна к отражению попыток нарушения защиты, однако совместима с протоколами типа Telnet и FTP.

Специальные пользователи[]

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

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

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

Эта идея аналогична анонимному пользователю в службах FTP. В Plan 9 серверы-гости FTP в дальнейшем сохраняются в специальном ограниченном пространстве имен. Она разъединяет пользователей-гостей и системные программы, такие как содержимое каталога /bin, однако позволяет сделать локальные файлы доступными для гостей, связывая их явно в пространстве. Ограниченное пространство имен более безопасно, чем обычная методика экспорта специального дерева каталогов; результатом является нечто вроде клетки вокруг пользователей, не внушающих доверия. Тем не менее бдительность по-прежнему необходима; Plan 9 облегчает построение безопасной системы, но не гарантирует этого.

Аутентификация с посредником[]

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

Права доступа к файлам[]

Одно из преимуществ построения служб как файловых серверов заключается в том, что проблемы владения и прав разрешаются естественным образом. Как и в Unix, с каждым файлом или каталогом связаны отдельные разрешения на чтение, запись и выполнение/поиск для владельца файла, группы и других пользователей. Трактовка группы необычна и состоит в том, что имя одного из пользователей может быть выделено как лидера группы (group leader). Если группа имеет лидера, то этот пользователь обладает специальными правами, такими как возможность изменения групповых прав файлов этой группы. Если лидер не установлен, члены группы считаются равными, как если бы каждый был лидером.

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

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

Другим необычным применением прав на файл является файловая система дампов, которая не только обслуживается тем же самым файловым сервером, что и исходные данные, но и представлена той же самой базой данных пользователя. Файлам в дампе, следовательно, дана защита, идентичная файлам в обычной файловой системе; если пользователь владеет файлом и тот защищен от чтения, та же самая картина сохранится и в файловой системе дампов. Кроме того, поскольку файловую систему дампов нельзя заменить, файл не может быть изменен; он навсегда останется защищенным от чтения.

Обсуждение[]

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

В Plan 9 основное внимание уделено файлам; предложенный механизм именования является основным фактором ее выразительности. В частности, при распределенных вычислениях принятый для наименования способ оказывает глубокое влияние на систему. Комбинация локального пространства имен и глобальных соглашений о взаимосвязи сетевых ресурсов позволяет избежать трудностей поддержания глобального однородного пространства имен, тогда как наименование всего как файлов делает понимание системы легкой даже для новичков. Рассмотрим файловую систему дампов, которая тривиальна в использовании для каждого, кто знаком с иерархической файловой системой. На более глубоком уровне, построение всех ресурсов над единым однородным интерфейсом делает интероперабельность легкой. Как только ресурс экспортирует интерфейс 9Р, он может прозрачным образом сочетаться с любой другой частью системы для построения необычных приложений; детали при этом остаются скрытыми. Это может звучать подобно объектно-ориентированному подходу, но на самом деле кое в чем от него отличается. Во-первых, 9Р определяет фиксированный набор «методов»; он не является расширяемым протоколом. Более важно то, что файлы хорошо определены и понятны и поступают предварительно скомпонованными со знакомыми методами доступа, защиты, наименования и обращения в сети. Объекты, несмотря на их общность, не поступают с этими определенными атрибутами. Редуцируя «объект» в «файл», Plan 9 без дополнительных усилий получает определенную технологию.

Тем не менее есть опасность развить идею вычислений, основанных на файлах, слишком далеко. Преобразование каждого ресурса в системе в файловую систему является в каком-то смысле метафорой, а метафоры могут приводить к конфузам. Хорошим примером ограничений является /proc, который только внешне выглядит как процесс, но не представляет его. Для исполнения процессов необходимы все еще обычные вызовы fork и exec, а не чего-то, подобное

cp /bin/date /proc/clone/mem Проблема с такими примерами в том, что для них нужно, чтобы сервер работал не под их управлением. Способность придавать значение командам, подобным указанным, не подразумевает, что это значение естественно выпадет из структуры ответов на запросы 9Р, которые она генерирует. Так, например, Plan 9 не помещает сетевые имена компьютеров в пространство имен файлов. Сетевые интерфейсы обеспечивают совершенно другую модель наименования, поскольку использование команд open, read и write над такими файлами не предоставляет подходящего места для кодирования всех деталей установки вызова для произвольной сети. Это не значит, что сетевой интерфейс не может быть файловоподобным, просто он должен иметь более четко определенную структуру.

Plan 9 имеет только один «официальный» механизм RPC, интегрированный с 9Р. По сравнению с системами с более общим RPC, такой подход имеет недостатки: полный вызов RPC должен быть реализован как write, за которым следует read, то есть требует вдвое больше команд; и некоторые специфичные формы RPC могут быть громоздкими. Например, реализация /dev/bitblt, которая имеет специальный RPC-подобный уровень, встроенный над 9Р, не может совместно использовать ни один из кодов для выстраивания сообщений 9Р и требует наличия сервера для сохранения состояния после некоторых вызовов write для возврата информации последующему вызову клиента read. С другой стороны, устройству Plan 9 присущи простота и общность, и (с некоторыми предосторожностями) ему не требуются компиляторы заглушек или какая-либо поддержка на языковом уровне. Громоздкость, подобная /dev/bitblt, на практике встречается редко и никогда не является ограничением. Более того, /dev/bitblt сама является примером, когда избыточность несущественна, т.к. основная масса вызовов устройств включает write без последующей read. Наконец, возможно наиболее важной является легкость написания сервера 9Р. Код, реализующий протокол, занимает всего 500 строк и обычно адаптируется из существующего сервера, а не пишется заново.

Что бы мы сделали по-другому в следующий раз? Некоторые элементы реализации нас не удовлетворили. Использование потоков для введения сетевых интерфейсов в ядре допускает, чтобы протоколы были связаны динамически, например для привязки одного и того же драйвера TTY к соединениям с TCP, URP и IL, но в Plan 9 такая способность к перестройке конфигурации не используется. (Она эксплуатировалась, однако, в том самом варианте ОС Unix, для которого и были изобретены потоки.) Замена потоков статичными запросами ввода/вывода упрощает код и делает его быстрее.

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

Хотя Plan 9 поддерживает отдельное пространство имен для каждого процесса, она не имеет никакого механизма для передачи описания пространства имен процесса другому процессу, кроме прямого наследования.

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

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

Литература

[1] American National Standards for Information Systems - Programming Language С, American National Standards lnstitute, lnc., New York, 1990.

[2] АТ&T Bell Laboratories, UNIX Time-Sharing System Programmer's Manual, Research Version, English Edition, Volume 1, Murray Hill, NX, 1985.

[3] TomDuff, Rc - А Shell for Plan 9 and UNIX systems, Proc. of the Summer 1990 UKUUG Ccmf., London,July, 1990, рр.21-33.

[4] IEEE, Information Technology - Portable Operating System Interface (POSIX) Part 1: System Application Program Interface (API) [С Language], New York, 1990.

[5] T.J. Killian, Processes as Files, USENlX, Summer 1984 Conf. Proc., June 1984, Salt Lake City, UT.

[6] В. Clifford Neuman, The Prospero File System, USENIX File Systems Workshop Proc., Ann Arbor, 1992, рр.13-28.

[7] John Ousterhout, Andrew Cherenson, Fred Douglis, Mike Nelson, and Brent Welch, The Sprite Network Operating Systems Operating System, IEEE Computer, 21(2), 23-38, Feb. 1988.

[8] Rob Pike, 8½, the Plan 9 Window System, USENIX Summer Conf. Proc., Nashville, June, 1991, рр. 257-265.

[9] Rob Pike, Dave Presotto, Ken Thompson, Howard Trickey, and Phil Winterbottom, The Use of Name Spaces in Plan 9, Ор. Sys. Rev., Vol. 27, No. 2, April 1993, рр. 72-76.

[10] Rob Pike, How to use thePlan 9 C Compiler, Plan 9 Programmer's Manual, Volume 2, АТ&Т Bell Laboratories, Murray Hill, N, 1995.

[11] Herman Chung-Hwa Rao, The Jade File System, (Ph D. Dissertation), Dept. of Сомр. Sci, University of Arizona, TR 91-18.

[12] Robert W. Scheifler and Jim Gettys, The Х Window System, АСМ Trans. on Graph, 5(2), рр. 79-109, 1986.

[13] Howard Trikey, АРЕ - The ANSI/POSIX Environment, Plan 9 Programmer's Manual, Volume 2, АТ&Т Bell Laboratories, Murray Hill, NJ, 1991.

[14] Brent Welch, А Comparison of Three Distributed File System Architectures Vnode, Sprite, and Plan 9, Computing Systems, 7(2), рр. 175-199, Spring, 1994.

Copyright © 2001 Lucent Technologies Inc. All rights reserved.

Источник: Открытые Системы

Advertisement