Технологии виртуализации вчера, сегодня, завтра

Эмуляторы виртуальных машин


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

У эмуляторов очень много преимуществ. Реализуемые ими виртуальные машины могут быть сколь угодно сложны и, что важнее, принципиально отличаться от реальной физической машины, средствами которой они поддерживаются. Одно и то же Java-приложение может быть запущено практически на любом «железе»; эмулятор Spectrum позволяет выполнять приложения, написанные для процессора Z80 на процессорах архитектуры x86; и т.д. Классические виртуализаторы всего этого делать, увы, не позволяют, - запустить, скажем, на x86, приложение для MacOS (использующее архитектуру PowerPC) с их помощью принципиально невозможно.

Слабые места эмуляторов вполне очевидны: поскольку аппаратные ресурсы процессора задействуются очень опосредованно (где можно было бы обойтись одной машинной инструкцией, приходится выполнять от сотен до десятков тысяч машинных инструкций для исполнения одной инструкции эмулируемого кода), то и производительность подавляющего большинства эмуляторов просто катастрофически мала. Даже в Java, разработчики которого прекрасно предвидели данную ситуацию и использованием сложного байт-кода постарались свести возникающий переизбыток работы к минимуму (чем проще инструкция, тем заметнее время, затрачиваемое эмуляторов на её «декодирование» - определение, что эта инструкция означает), полностью избавиться от этих проблем, к сожалению, не удалось: «тяжелые» Java-приложения ощутимо «тормозят» и потребляют большое количество оперативной памяти.


Несколько раз предпринимались серьезные попытки исправить данное положение дел, отказавшись от исполнения кода «на лету», когда эмулятор последовательно, инструкция-за-инструкцией, транслирует программу, и перейдя к «динамической компиляции программ», когда программа, записанная в одной системе команд предварительно «переводится» в «родную» систему команд данного процессора, и уже затем, в виде полученного «родного» кода на этом процессоре исполняется. К примеру, разработанный Connectix, позднее купленной Microsoft, продукт Virtual PC for Macintosh позволял, за счёт подобного «перекомпилирования» приложений для операционных систем Microsoft, запускать эти приложения на компьютерах Apple Macintosh. А компания Transmeta в 1999 году даже выпустила совершенно уникальный процессор Crusoe (VLIW-архитектуры), который имитировал «видимость» x86-архитектуры при помощи специального полуаппаратного эмулятора, разработанного, к слову, с участием Линуса Торвальдса. А позднее Microsoft разработала на основе данного подхода и «усовершенствованную альтернативу» Java - технологию .Net, использующую для записи программ специальный «универсальный код» CIL (Common Intermediate Language), который по своей сути аналогичен псевдокоду, который генерируют в ходе своей работы современные компиляторы перед тем, как сконвертировать этот «абстрактный код» во вполне конкретные машинные инструкции.

Потенциально данный подход лишён всех «узких мест», связанных с недостаточной производительностью обычных эмуляторов, однако технология .Net до сих пор так и не получила обещанного распространения, а производительность Virtual PC for Macintosh, равно как и Transmeta Crusoe, оставляет желать лучшего.


Содержание раздела