System Licensed Internal Code (SLIC) — сердце AS/400
Впереди скользкая дорога
Ответ: Внутренний код для систем с RISC-процессором — SLIC (System Licensed Internal Code). Хотя, несомненно, придумавшие это имя разработчики имели в виду значение слова slick на сленге ("чудесный", "замечательный", "первоклассный"), а не свойства зимних миннесотских дорог2Slick — скользкий. — Прим. переводчика..
Когда в 1991 году в Рочестере начались работы над RISCпроцессором, потребовалось внести множество изменений в LIC, расположенный под MI. Некоторые компоненты (но не все!) должны были быть полностью переработаны. Большая часть существующего LIC также требовала реструктуризации. Этот код уже претерпевал частые изменения и модернизации при создании новых моделей System/38 и AS/400.
Из-за множества изменений производительность работы программистов над этой частью системы уменьшалась, а расходы на сопровождение росли. Моральный дух наших программистов, постоянно латавших старый код, тоже падал.
До перехода на RISCпроцессоры нам нужно было еще выпустить три новых версии VLIC, изза чего мы не могли полностью переключиться на SLIC. Поэтому для создания новой ОС было решено создать специальное подразделение во главе с Майком Томашеком. Входившие в его состав инженеры могли выбирать любые методы разработки по своему усмотрению.
На совещании по выработке плана действий эта группа рассмотрела два подхода к модернизации LIC. Первый состоял в том, чтобы заново спроектировать и написать низкоуровневые компоненты, затронутые изменением процессора. Второй — переместить эти затронутые компоненты в аппаратуру RISC с минимальными изменениями. Данный тип миграции ПО без изменения логики работы программы часто называется переносом. Все остальные компоненты, не затронутые изменением процессора, такие как база данных, должны были быть перенесены с минимально возможными модификациями.
Майк и его команда решили перепроектировать и переписать затронутые компоненты заново. Это было нелегким решением, так как большая часть низкоуровневого кода основывалась еще на первоначальном проекте System/38 и интенсивно настраивалась для повышения производительности в течение 15 версий системного ПО. Не все верили в успех: ведь предстояло полностью изменить лишь "начинку" переписываемых компонентов, оставив в неприкосновенности все интерфейсы, чтобы не затронуть переносимые компоненты. Кроме того, надо было учесть возможность расширений ПО в планируемых новых версиях AS/400. В общем, все это напоминало стрельбу по движущейся мишени.
Билл Берг — один из десяти специалистов, рекомендовавших использовать PowerPC для AS/400, — продвигал идею сократить время разработки, использовав объектно-ориентированное программирование (ООП). Объектно-ориентированные языки приобрели популярность конце 80-х как способ быстрого создания программ и уже были достаточно совершенными, чтобы использовать их в таком большом проекте. Билл Армстронг (Bill Armstrong) и Дик Мастейн (Dick Mustain) — также твердые сторонники объектноориентированной разработки — были с ним согласны. Пол Мэттисон (Paul Mattison) собрал команду и подготовил план действий. Поддержка ключевых разработчиков также доказала, что новая технология программирования поможет обеспечить делу успех. Кроме того, мы собирались нанять новых людей.
Концепции объектно-ориентированного программирования
Давайте кратко рассмотрим основные элементы и термины ООП. Объект — это основной элемент программы, объединяющий в себе данные и операции над ними. Операция, которую может выполнить объект, иногда называется методом. Внутренняя структура данных и реализация методов объекта скрыта от остальной программы. Это называется инкапсуляцией. Программе доступен только интерфейс объекта. ООП отличается тем, что объединяет операции и данные воедино (при процедурном программировании операции отделены от данных).
Подход ООП предполагает повторное использование ПО. Основной механизм обеспечения повторного использования — класс, представляющий собой шаблон, описывающий все объекты, для которых характерны одинаковые операции и элементы данных. Следовательно, может быть создано много объектов каждого из классов. Часто они называются экземплярами объекта.
Для существующего класса можно создать подклассы путем использования наследования. Наследование позволяет программисту и создавать новые подклассы, и повторного использовать код, а также данные базового класса без их повторения. Вновь полученные подклассы настраиваются так, чтобы соответствовать конкретным потребностям приложения. Способность подклассов одного класса отвечать на одно и то же входящее сообщение поразному называется полиморфизмом. Полиморфизм объединяет концепции наследования и динамического связывания (dynamic binding).
Наборы объектов, созданные из классов и подклассов, могут быть объединены для построения необходимых сервисов ОС. После определения достаточно сложного набора классов (называемого библиотекой классов), программисты могут использовать классы этого набора, а не программировать заново функции, предоставляемые классами.
Однако в объектноориентированной технологии есть и недостатки. Производительность ядра ОС чрезвычайно важна, так как сильно влияет на производительность системы в целом. Исследования приложений для AS/400 показали, что значительная часть длинных цепочек команд приходится на код ОС. А при применении объектно ориентированной технологии для некоторой функции повторно используется большое число маленьких модулей, и общая длина цепочек команд увеличивается, по сравнению с реализацией той же функции как единого целого. Группе пришлось включить в план работ время для выполнения тонкой настройки таких функций, чтобы сохранить показатели производительности ядра, достигнутые за предшествующие годы его разработки3Оптимизация кода LIC продолжалась долгие годы после создания первого ядра RISC. В результате при выходе версии V3R7 на рынок, некоторые покупатели отметили 50процентный рост производительности. После выпуска V4R1 на некоторых конфигурациях системы был отмечен новый рост производительности без необходимости замены аппаратуры. Настройка ядра любой ОС — это бесконечный процесс..
Среда разработки SLIC
Группа разработчиков должна была выбрать язык программирования. Язык программирования VLIC, называвшийся PL/MP и использовавшийся со времен разработки оригинальной System/38, был основан на языке PL/I. MP в его названии расшифровывается как Machine Product — имя, которое часто использовалось для обозначения аппаратных средств и обоих слоев микрокода. Компилятор PL/MP, как и ассемблер IMPI, генерировал двоичные машинные команды IMPI.
Язык PL/MP не пригоден для ООП, но его попрежнему использовали для тех компонентов, которые не переписывались. А для остальных был разработан новый компилятор PL/MP, генерировавший двоичный код для PowerPC. Кроме того, было создано специальное средство переноса программ, которое сканировало код, отыскивая зависимости от IMPI, прежде чем преобразовать его в новый PL/MP.
В течение ряда лет мы пытались использовать другие языки при разработке компонентов VLIC. Например, один из наших новейших трансляторов был написан на Modula2, применялся также язык С. Однако, мы чувствовали, что ни один из них не подходит для проекта, основанного на объектно-ориентированной технологии. Выбор напрашивался сам собой — язык C++. Нам нужно было разрабатывать код ОС очень низкого уровня. Иногда, для достижения оптимальной производительности приходилось прибегать к ассемблеру, и С++ легче позволял это. Ведь, фактически, язык С++ и есть современный вариант ассемблера4Дик Бэйнс любит сравнивать языки программирования с куском мыла. Например, он говорит, что программирование на RPG напоминает попытку отрезать кусок мыла пластмассовой ложкой. Программирование же на С++ похоже, по его мнению, на отрезание того же куска с помощью обоюдоострой бритвы: можно быстро делать очень точные разрезы, но по окончании процедуры все мыло будет в крови..
Другим преимуществом С++ была возможность легко найти людей, его знающих. Для этого проекта нам было нужно много новых программистов, и начался массовый найм. Скоро над проектом SLIC работало более 200 человек.
Решение было предложено Крисом Джонсом. Согласовав свои действия с другими руководителями проекта, он нашел стороннего консультанта — эксперта как в объектноориентированной технологии, так и в программировании на С++. Никогда ранее мы не обращались "на сторону" по подобным поводам. У IBM были внутренние программы обучения, и персонал, который этим занимался. Разумеется, приглашение на работу чужака было воспринято в штыки. Крис настаивал и убедилтаки руководство нанять консультанта для интенсивного шестинедельного обучения наших сотрудников. Мы даже специально выгородили прямо посередине отдела разработки классную комнату, которая использовалась исключительно для обучения.
Возможность повторных итераций при разработке — фундаментальное преимущество ООП, но при ее использовании трудно оценить, в какой степени мы продвинулись вперед. Прием, который мы использовали для "измерения прогресса", заключался в так называемых BUB (Bring up Bind). Каждый BUB представлял собой группу объектов, реализовывавших четко определенный набор функций ОС, и имевшую общий интерфейс с другими компонентами. Путем сравнения BUB с другими компонентами, мы могли оценить, как продвигается разработка. Кроме того, BUB позволили нам действовать в определенном порядке, а также вызвали переделку известного рекламного лозунга Budweiser: "This BUB’s for you"6Дословный перевод: "Эта бутылка Будвайзера для Вас". — Прим. консультанта..
Технология ООП не подвела: производительность программистов при разработке SLIC повысилась почти в четыре раза по сравнению с традиционной методикой. В период с июля 1992 года, было создано более миллиона строк кода на С++ и более 7000 классов. Считая весь перенесенный код, ниже MI работает более 3 миллионов строк кода ОС.
Затраты на разработку SLIC
Создание вычислительной системы с высокоуровневым машинным интерфейсом и значительной частью ОС, расположенной под этим интерфейсом, было связано с определенными затратами. На разработку ПО пришлись основные расходы, связанные с AS/400. Давайте ненадолго остановимся и рассмотрим, почему так получилось.
SLIC содержит 3 миллиона строк надежного кода. (Под надежным имеется в виду код, который всегда должен работать правильно, чтобы обеспечить целостность и защищенность системы.) Так как SLIC — ядро ОС, мы не защищаем один его компонент от другого. Это совершенно обычный подход: ядра большинства ОС защищены от кода, расположенного вне его, но весь код внутри ядра считается надежным.
Если ядро невелико, скажем, состоит из 100 тысяч строк кода, то его целостность очень легко протестировать при каждом изменении. Если же строк 3 миллиона, то такое тестирование становится и сложнее, и дороже. Много лет мы в Рочестере использовали следующий подход: строго ограничивали круг тех, кому позволено работать с ядром, группой разработки и тестирования. Таким образом, код для SLIC могут написать заново только разработчики из Рочестера (впрочем, это достаточно большое число людей). Дополнительно надежность гарантируется тем, что разработчики действуют в условиях жесткой организационной структуры.
У подобного подхода есть и свои недостатки. Неоднократно сторонние организации, включая другие подразделения IBM, запрашивали у нас разрешение написать функции для SLIC. Во всех случаях мы отвечали твердым отказом: если позволить кому-либо написать хотя бы малую часть SLIC, то это может нарушить целостность всей системы, чего мы не допустим. Но следствие такого подхода — то, что создание новых функций SLIC жестко зависит от возможностей наших программистов. Мы практически никогда не можем позаимствовать код у коголибо еще в IBM, по крайней мере, не на уровне SLIC.
В "Машинный интерфейс, независимый от технологии" мы рассмотрим, как компиляторы ЯВУ генерируют код PowerPC, исполняемый ниже MI. Мы увидим, что это требует использования компонента SLIC, известного как транслятор. Как и все компоненты SLIC, транслятор надежен, то есть должен всегда генерировать код, чтобы не нарушить целостность или защиту других компонентов системы. Трансляторы также разрабатываются только в подразделении SLIC в Рочестере.
Хорошо, что все функции SLIC работают как единое целое. Так как весь SLIC разрабатывался под одной крышей, мы достигли уровня целостности, о котором можно только мечтать в системах, разработка которых ведется "кусками". Использование общих программных компонентов в разных ОС может значительно сократить затраты, но не даст той интеграции функций, которой обладает AS/400. Что касается общих компонентов, то как мы увидим в следующем разделе, и здесь существует возможность подключения без нарушения целостности.
Технологии ядра в SLIC
В прошлом ядро каждой ОС было уникальным, мало кто брался разрабатывать ядро отдельно от ОС. Однако в середине 80х годов положение стало меняться. В некоторых университетах, например, в КарнегиМеллон (CarnegieMellon), начали изучение возможности использовать ядро с несколькими ОС. Именно там было спроектировано микроядро Mach, представляющее собой подмножество ядра, и выполняющее функции, необходимые большинству ОС.
Если одно и то же микроядро лежит в основе двух или нескольких ОС, то возможно исполнять эти ОС параллельно на одном и том же процессоре. Более того, такие ОС могут очень эффективно разделять ресурсы и взаимодействовать друг с другом. В последние годы операционные системы, выполняющиеся поверх одного микроядра, стали называть индивидуальностями (personality).
Так как SLIC разрабатывался в качестве нового ядра ОС, имело смысл включить в него технологии для поддержки множественных индивидуальностей. Фактически, большая часть такой поддержки уже имелась в оригинальном LIC. Например, для распределения процессора между ОС микроядро использует механизм передачи сообщений. Аналогичный подход использовался в оригинальной System/38 и был перенесен оттуда на AS/400. Подробно мы рассмотрим этот механизм в "Управление процессами" .
В то время, когда мы разрабатывали SLIC, в IBM были проведены исследования в области применения общих компонентов ОС на всех системах IBM, включая использующие процессор PowerPC. Одним из основных предложений было — принять в качестве базовой модели микроядро IBM, сконструированное по принципам микроядра Mach. В SLIC уже имелось большинство технологий микроядра, но возникали сомнения: следует ли нам в качестве всеобщей основы использовать микроядро IBM?. Ответ был совершенно очевиден. Единственно существовавшим в то время было 32-разрядное микроядро. Чтобы использовать это микроядро для AS/400, нужно было бы создать 64-разрядную версию. Перспективы возможности разделения ПО были также довольно туманны, кроме того, оставались вопросы по поводу масштабируемости этого микроядра (сколько пользователей сможет оно поддерживать?). Поэтому мы отвергли мысль использовать его в качестве основы для SLIC. Однако в Рочестере была создана группа для разработки 64-разрядных модификаций микроядра IBM с прицелом на будущее. Было также решено включить в SLIC возможности по поддержке множественных индивидуальностей ОС.
Добавление в SLIC поддержки других ОС, на первый взгляд, не имело смысла. Какие еще ОС, кроме OS/400, нам следует поддерживать? Некоторые из нас все понимали, но были вынуждены пойти на небольшую хитрость, чтобы показать, как эта поддержка могла бы работать.