Прикладные виртуальные машины

18 ноябрь, 2010 - 16:48Андрей Зубинский

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

Наиболее интересное, что мы можем рассмотреть сегодня в актуальных пользовательских ОС, претендующих на роль самых массовых (потому что речь идет о системах, ориентированных на носимые устройства – смартфоны, коммуникаторы, планшеты и сверхлегкие компактного формфактора лэптопы), начиналось в далеких... 1960-х годах. Именно тогда, во второй половине 60-х, выпускник и преподаватель Кембриджа Мартин Ричардс (Martin Richards) разработал язык программирования BCPL – тот самый BCPL, который впоследствии стал основой языка B (автор – Кен Томпсон), а из B и собственного таланта чуть позже Деннис Ричи создал то, что до сих пор в силу чуть ли не оружейного сочетания красоты и уродства остается одним из столпов программирования – язык C. Во всей этой истории из-за яркости главной системы, разработанной на C, ОС UNIX, надолго затерялась одна исключительно важная деталь, сегодня становящаяся куда более важной, чем и C, и UNIX (в дальнейшем это утверждение станет понятным). А именно, среда исполнения BCPL фактически основывалась на виртуальной машине. Если быть точным, то не совсем так, конечно – транслятор BCPL использовал специальное промежуточное представление, OCODE, которое зависимый от архитектуры целевой машины генератор кода транслировал в конкретные машинные команды. Но. В сохранившейся до сих пор документации BCPL (PDF-файл доступен по адресу goo.gl/0PRE) на 128 с. (нумерация страниц файла, а не документа) приводится описание «Абстрактной машины OCODE». Это вычислитель стековой архитектуры, в котором для размещения динамических переменных используется стек (что облегчает автоматическое управление памятью при входе-выходе из процедур, например), статические данные и исполняемый код располагаются в области памяти программ, а для глобальных данных предусмотрена отдельная область памяти (глобальный вектор). BCPL, основанный на этом раннем механизме виртуализации, стал на самом деле отправной точкой и направляющим вектором отдельной по-настоящему культовой ветви развития операционных систем, в силу определенных обстоятельств практически миновавшей массового потребителя продуктов ИТ в бывшем СССР. Дело в том, что автор BCPL Мартин Ричардс не остановился на разработке языка и примерно через десять лет в альма-матер (в Кембридже, где он преподавал до 2007 г.) создал собственную мобильную ОС – TRIPOS, написанную на BCPL. Как и первые версии UNIX, TRIPOS «бегала» на самом университетском компьютере тех времен – PDP-11, впоследствии была портирована на опять же самое ходовое университетское «железо» Data General Nova (машина этого семейства – отдельная история, заслуживающая, наверное, музея), затем – на вычислители с центральным процессором всех цивилизованных народов тех времен – Motorola 68000. Как и UNIX, TRIPOS вырвалась из университетских стен и стала, если так можно сказать, ОС-невидимкой интересной судьбы. Очень интересной судьбы. Потому что TRIPOS, чьи ядро и драйверы писались на ассемблере целевой машины, а весь пользовательский уровень фактически был надстроен над виртуальной машиной OPCODE, стала основой... культовой ОС Amiga, модулем AmigaDOS, обеспечивающим работу файловой системы и пользовательский интерфейс командной строки этой системы. В действительности TRIPOS даже куда интереснее и заслуживает более пристального внимания – во времена дорогих вычислительных мощностей и тактовых частот, измеряющихся единицами мегагерц, в TRIPOS, в отличие от той же ровесницы UNIX, вместо системных вызовов использовался полноценный и по меркам того времени оригинальный механизм передачи сообщений (предусматривающий вместо трансляции пакетов передачу только указателя на неперемещаемое тело пакета), что обеспечивало достаточно высокое быстродействие ОС в целом. Самое неожиданное в этой истории – факт удивительного долгожительства TRIPOS как независимой самостоятельной ОС. В это трудно поверить, но... TRIPOS до сих пор является живым коммерческим продуктом (на крохотной, не обновляемой с 2002 г. странице автора этой ОС никаких изменений в статусе системы не наблюдается – goo.gl/1A85), сопровождением которого занимается британская компания Open GI. Это почти фантастика, но терминальные системы с TRIPOS-сервером (в основе его аппаратной части все те же знаменитые Motorola семейства 68K) и прикладное программное обеспечение по сей день используются рядом английских страховых компаний. Итак, соберем все факты в одном предложении – транслятор BCPL, созданный во второй половине 60-х годов, базировался на виртуальной машине OPCODE, затем этот транслятор стал основой пользовательского уровня ОС TRIPOS, а она, в свою очередь, мигрировала в основу ОС Amiga – одну из самых совершенных пользовательских ОС своего времени, и сама TRIPOS, и ОС Amiga оказались очень живучими, несмотря на то, что при дорогих вычислительных ресурсах в них применялись и виртуализация, и механизм передачи сообщений (который до сих пор многими считается «дорогим»).

Примерно в тот же временной период, о котором идет речь, разработчики UNIX предложили принципиально иной способ «виртуализации», за реализацию которого отвечает не виртуализированная среда исполнения, а стандартизированные синтаксис и семантика языка программирования в сочетании с открытым описанием системных вызовов ОС и эталонной реализацией кода системы. К чему привел этот подход – предмет отдельного обсуждения, выходящего за рамки статьи.

За BCPL и OPCODE последовал период куда более известной виртуальной машины (ВМ) – P-CODE для языка Pascal. Что характерно – виртуализация с помощью ВМ (а не на основе UNIX-модели) больше привлекала европейцев – в 1973 г. в знаменитом уже только по имени Никласа Вирта цюрихском ETH была разработана система программирования Pascal-P, основанная на виртуальной стековой машине. Через два года сам Вирт написал компилятор Pascal-S для этой же ВМ, и началось триумфальное шествие P-CODE по миру. И это не преувеличение – задолго до Java для ВМ P-CODE выпускались серийно аппаратные системы (в семействе компьютеров Pascal MicroEngine производства Western Digital P-CODE был реализован на уровне микропрограмм процессоров), была создана полностью виртуализированная кросс-платформенная ОС (BOS, Business Operating System британской компании CAP исполнялась основными массовыми процессорами того времени – i8080, Motorola 6800, Zilog Z80, и на момент выхода на рынок IBM PC XT один BOS-сервер уже обслуживал до восьми терминальных клиентов!). Значимость P-CODE усилил выход знаменитой «калифорнийской версии» UCSD Pascal и мобильной ОС p-System. ВМ с системой команд P-CODE стала настолько значимым явлением, что следы ее легко просматриваются в далеких от Pascal артефактах, например, Microsoft поддерживала генерацию P-CODE во всех своих 16-битовых компиляторах.

Прикладные виртуальные машины
Необычная в наше время трассировка платы компьютера Data General Nova как будто отражает странности движения идеи прикладных виртуальных машин. Но во всем можно и увидеть красоту, и найти логику

Идея виртуализации пользовательского уровня ОС с помощью стековой ВМ еще с конца 50-х годов расширялась в системную область и доводилась, наверное, до предела Чарльзом Муром в его «системе всего» Forth. Изящная крохотная конструкция Forth в рамках единой модели ВМ объединяет собственно ОС, транслятор языка программирования, командную пользовательскую оболочку, среду разработки программ, комплект утилит и чуть ли не все, что можно себе представить. Forth получилась очень специфической системой, не похожей ни на что вообще. И остается такой по сей день. Широкого распространения она не получила, но нашла области применения во встраиваемых системах (откуда постепенно вытесняется), стала в какой-то мере прообразом специализированных ВМ (PostScript, например) и... приобрела неисчислимое количество поклонников среди профессиональных программистов и просто любителей. Пожалуй, Forth – самая виртуализированная из всех виртуализированных ОС в истории.

Еще один очень важный игрок в истории виртуализации пользовательского уровня ОС с помощью прикладной ВМ – ОС Inferno, в команде ключевых разработчиков которой был ныне сотрудник Google, хорошо известный всем, кто использует ОС UNIX-семейства, Роб Пайк. В Inferno весь пользовательский уровень – надстройка над ВМ Dis. И в особенностях Dis, пожалуй, заключается важнейшая деталь. До Dis все массовые прикладные ВМ имели стековую архитектуру. Потому что она проста в реализации и обеспечивает своим принципом действия поддержку эффективного промежуточного кода при трансляции языков высокого уровня. Dis же – регистровая виртуальная машина. То есть фактически моделирующая некий вполне реализуемый «в железе» традиционный процессор. Логика возникновения регистровых ВМ проста – пока разработка компиляторов была искусством, создатели ВМ вынуждены были искать компромисс между сложностью реализации компилятора и сложностью трансляции промежуточного кода в машинный. К 80-м годам компиляторы стали разделом технологии, и эффективность исполнения виртуального кода реальной машиной вышла на первый план. А регистровые ВМ намного лучше «отображаются» на реальное же регистровое «железо».

Эта не совсем полная предыстория не только показывает, что у двух главных прикладных ВМ современности – Java и CLR из состава .NET – были достойные внимания предшественники. Она объясняет логику современных разработчиков двух виртуализированных массовых пользовательских ОС – Android (в которой, к слову, используется весьма интересная и специфическая регистровая ВМ Java – вспомните, где теперь работает Роб Пайк) и Windows Phone 7. Виртуализация в этих системах – способ сделать их открытыми для модификаций на пользовательском уровне и стабильными – на системном. Иными словами – способ избежать проблем с сегментацией, которые выявила история ОС UNIX c «договорным» подходом к виртуализации. Если проанализировать краткий исторический обзор, – это, пожалуй, самый здравый подход к обеспечению живучести проектов.