25. Виртуальные машины
Реальные машины состоят из материальных подвижных частей и, как правило, называются в соответствии с задачами, для выполнения которых они сконструированы. Дизайн газонокосилок, открывашек и кофемолок бывает разным. Порой в основе их работы даже лежат разные физические принципы, но кое-что остается неизменным: машины, которые называются одинаково, выполняют более или менее одинаковую работу. Возможно, некоторые из них выполняют ее лучше других, но все зависит от предпочтений пользователя. Домовладелец может выбрать медленную газонокосилку, которая работает тише; владелец кафе может выбрать кофемолку, которая имеет больше степеней помола, пускай пользоваться ею и сложнее. Некоторые машины универсальны: надев другую насадку, можно превратить дрель в пилу или шлифовальную машинку. Компьютеры тоже универсальны, но могут делать не десяток, а целую тучу разных вещей. Вместо того чтобы надевать для выполнения каждой задачи новую насадку, вы открываете новую программу – очень длинную последовательность нулей и единиц, – которая ставит все необходимые внутренние переключатели в нужное положение, чтобы выполнить задачу. Каждая схема настройки – это уникальная машина, уникальная виртуальная машина, машина “из инструкций”, а не из подшипников, шестеренок, блоков и проводов. В компьютерах инструкции могут заменять блоки и шестеренки, потому что вместо хлебного теста, целлюлозы и стальных болванок компьютеры обрабатывают информацию, а информацию всегда можно перевести в двоичный код, состоящий из нулей и единиц, единственный код, который компьютер может – и имеет необходимость – “читать”. Микросхемы на кремниевых подложках манипулируют триллионами этих нулей и единиц, временно открывая и закрывая шлюзы, переводя потоки информации к той или иной микросхеме и таким образом контролируя, что с ней происходит. Миллионы крошечных элементов аппаратного обеспечения, которые могут принимать одно из двух состояний – 0 или 1, – это единственные “подвижные части” машины, и от настроек тысяч или миллионов этих крошечных элементов зависит то, какой именно машиной является компьютер в конкретный момент времени.
Виртуальной называется машина, которая возникает, когда определенный набор инструкций (а точнее, диспозиций) применяется к реальной машине, обладающей высокой пластичностью, то есть машине, взаимодействующие элементы которой могут пребывать в большом количестве разных состояний. Поскольку виртуальная машина работает с информацией, она может выполнять ту же задачу, что и компьютер, в котором роль “подвижных частей” играют изменения состояния аппаратного обеспечения, производя все эти изменения в представлениях этих подвижных частей. Вы можете выполнять деление столбиком, записывая процесс карандашом на бумаге, но деление столбиком дается вам особенно хорошо, так что вы можете производить его “в уме”, просто представляя – или воображая – цифры на листе или классной доске. Поскольку речь идет об информации, результат всегда один: вы получаете ответ. Напротив, если вы представите себе бутерброд с ветчиной, почувствовав голод, настоящего бутерброда это не заменит. Компьютеры так хорошо справляются с информационной работой “в уме” (представляя машину, которая выполняет работу), что практически невозможно сказать, с какой машиной вы при этом имеете дело – с “особой”, “аппаратно-реализованной”, ориентированной на выполнение конкретной задачи по обработке информации машиной или же с виртуальной машиной, работающей на многоцелевой микросхеме. К примеру, подавляющее большинство крошечных, дешевых компьютерных микросхем, которые используются сегодня в лифтах, кондиционерах, машинах, холодильниках и пультах дистанционного управления, на самом деле представляют собой многоцелевые компьютеры, способные выполнять вариации всех программ, установленных на вашем ноутбуке, но обреченных всю жизнь выполнять единственную относительно простую программу (программу регулировки зажигания, цикла разморозки и т. д.), “вшитую” в ПЗУ, и эта программа ограничивает все их выдающиеся способности одним-двумя трюками. Это дешевле изготовления микросхем специального назначения, разработанных для выполнения только этих простых задач.
Концепция виртуальной машины – один из лучших стимуляторов воображения, которые пришли к нам из компьютерной науки. Она успела доказать свою состоятельность в сфере информатики, и теперь ее пора применять в других сферах. Я использую этот термин в более широком смысле (и в свое время я объясню почему), поэтому не лишним будет узнать, каково его изначальное – как скажут некоторые, истинное – значение. Термин предложили специалисты по теории вычислительных систем Джеральд Попек и Роберт Голдберг (1974). Изначально он означал “эффективный, изолированный дубликат реальной машины” – дубликат, состоящий из… инструкций. Реальная машина – назовем ее А – это настоящий аппарат, сконструированный из кремниевых чипов, проводов и тому подобного, а виртуальная машина – это компьютерная программа (выполняющаяся на другой реальной машине, машине Б), которая полностью имитирует аппаратное обеспечение машины А: она может работать немного медленнее, потому что ей приходится составлять все базовые операции машины А из базовых операций, доступных на ее собственном аппаратном обеспечении, машине Б, но при этом выполняет те же самые программы. Программа, написанная для выполнения на аппаратном обеспечении А, должна без проблем выполняться и на аппаратном обеспечении Б, если на аппаратном обеспечении Б работает виртуальная машина, имитирующая машину А.
Этот фокус удивительно полезен – и не только из-за явной экономии, которую он предполагает: скажем, у вас нет компьютера на Mac OS, но есть дорогое программное обеспечение, работающее только на Mac OS. В таком случае вы можете написать виртуальную машину (ВМ), имитирующую Mac OS на вашем компьютере на Windows, и тогда программы для Mac OS будут работать на вашем компьютере при запущенной ВМ Mac OS. Ваш компьютер на Windows будет “притворяться” компьютером на Mac OS, но программы ничего не поймут! Представьте человека, который сломал руку. Ему наложили гипс, который сильно ограничивает подвижность руки, а его вес и форма также требуют корректировки остальных движений тела. Теперь представьте мима (скажем, Марселя Марсо), который изображает человека с загипсованной рукой. Если мим хорош в своем деле, движения его тела будут ограничиваться ровно так же: у него на руке виртуальный гипс – и он “практически виден”. Компьютер на Windows, имитирующий компьютер на Mac OS с применением ВМ Mac OS, должен быть неотличим – для программного обеспечения, работающего на нем, и для стороннего наблюдателя – от настоящего компьютера на Mac OS.
В реальности все обычно наоборот. Хотя и есть сконструированные ВМ Mac OS, работающие на Windows, насколько мне известно, это скорее баловство, чем настоящее, практичное программное обеспечение. Напротив, для Mac OS созданы надежные, удобные в использовании ВМ Windows, которые позволяют владельцам компьютеров на Mac OS запускать любые программы, написанные для Windows. Большинство программ сегодня создается без привязки к конкретному аппаратному обеспечению, но с привязкой к конкретным операционным системам (которые, в свою очередь, работают на разном аппаратном обеспечении). Первая причина расширить определение виртуальной машины – необходимость включить в него виртуальные имитации операционных систем. Операционная система тоже представляет собой своеобразную виртуальную машину, позволяя немного разному аппаратному обеспечению выполнять одни и те же программы, но операционная система – это исключительно программное обеспечение; она не имитирует настоящее аппаратное обеспечение, но создает – фактически задавая конкретные условия – воображаемую машину, которая подчиняется определенным правилам, принимает определенные данные и так далее.
Другая причина расширить определение заключается в том, что одной из самых популярных и широко распространенных виртуальных машин сегодня является виртуальная машина Java, или JVM, которая, подобно операционной системе, не имитирует никакую аппаратно-реализованную машину, а существует только в форме программно-реализованной машины. Именно изобретению Java интернет в основном обязан своей универсальностью: Java позволяет скачивать с сайтов маленькие программы – Java-апплеты, – которые дают возможность разгадывать кроссворды, играть в судоку, изучать карты, увеличивать фотографии, играть в игры с людьми с другого конца света, а также решать множество “серьезных” вычислительных задач. Создавая программы на языке программировании Java, веб-дизайнер не должен знать, кто именно придет к нему на сайт – пользователи Mac OS, Windows (или Linux), – поскольку Java-апплет всегда запускается на JVM, сконструированной специально для работы на компьютере на Mac OS, Windows или Linux. Соответствующая JVM автоматически скачивается и за несколько секунд устанавливается на ваш компьютер, а затем Java-апплет, как по волшебству, выполняется на этой JVM. (Возможно, вы замечаете, как на ваш компьютер скачиваются обновления Java, а возможно, и не замечаете этого! В идеале вы можете забыть о том, какая JVM установлена у вас на компьютере, и ожидать, что каждый посещаемый вами сайт либо будет использовать Java-апплеты, которые уже работают на вашей JVM, либо соответствующим образом обновит Java для корректной работы.)
Таким образом, в соответствии с моим расширенным определением термина, виртуальной машиной можно считать практически любую компьютерную программу, поскольку она представляет собой программное обеспечение – систематический список инструкций, – при запуске превращающее универсальный компьютер в машину конкретного назначения, которую можно было бы сконструировать и подключить в качестве аппаратного обеспечения. Алан Тьюринг сделал блестящий вклад в науку – и оказал огромную услугу человеческой цивилизации второй половины двадцатого века, – предложив идею “универсального” компьютера (сегодня мы называем его универсальной машиной Тьюринга), который можно превратить в любой другой компьютер, созданный для конкретной цели, просто установив и запустив соответствующую программу! (Если вы решили пропустить главу 24, то имейте в виду: в ней об этом говорится подробнее.) Не нужно создавать все возможные конфигурации аппаратного обеспечения – хватит и одной, ведь все остальное сделает программное обеспечение. Со времен Тьюринга нам известно, что можно взять сложную штуковину – аппаратное обеспечение, – обладающую большой пластичностью – регулируемыми ячейками “памяти” или регистрами, – и поместить в эти ячейки памяти набор инструкций, при выполнении которых эта штуковина превратится в любой компьютер, какой нам под силу ясно вообразить.
Машина Тьюринга – или ноутбук – выполняет по одной инструкции зараз и переходит к следующей инструкции, но “параллельные” компьютеры могут выполнять много (миллионов) инструкций одновременно. Регистр – это любой фрагмент аппаратного обеспечения, который может пребывать в том или ином состоянии (например, в состоянии нуля или единицы в случае с компьютерными битами, но состояний может быть и больше двух), пока не получит команду изменить состояние. Любая система регистров, которая может производить определенные элементарные операции на основании этих состояний (к примеру, менять состояние регистра или использовать состояние регистра, чтобы определить, какую операцию выполнять дальше), может и настраивать свои регистры таким образом, чтобы “вычислить функцию” или “исполнить программу”. Получается, что на любом подобном аппаратном обеспечении может работать виртуальная машина, созданная для использования этих простых шагов. Этот фокус можно проворачивать не один, а много раз, устанавливая виртуальные машины на виртуальные машины на виртуальных машинах… на аппаратном обеспечении.
Рассмотрим шахматную программу, написанную на высокоуровневом языке программирования Common Lisp, запущенную на операционной системе Windows 7, запущенной на компьютере. Этот компьютер притворяется машиной Windows, которая притворяется машиной Lisp, которая притворяется машиной для игры в шахматы. Если рассмотреть детали программы на высшем уровне, они будут более или менее понятны подкованному в компьютерах и шахматах наблюдателю (“Ага! Эта подпрограмма генерирует все возможные ответы на перемещение слона, а затем запускает подпрограмму оценки, которая…”). Настоящий программный код той же программы – последовательность нулей и единиц, которая помещается в регистр инструкций аппаратного обеспечения, – напротив, способен свести любого с ума, поэтому мы благоразумно сосредотачиваем внимание на высших уровнях. На каждом уровне мы видим лес за деревьями, поскольку детали низших уровней весьма кстати скрыты от наших глаз. Параллель между каскадом виртуальных машин на компьютере и каскадом гомункулов в гомункулярнофункционалистском представлении о сознании не просто совпадение. Именно необычайный успех виртуальных машин, которые помогли нам понять, как решать немыслимые ранее задачи (бронирование авиабилетов, игру в шахматы, прогнозирование погоды, письмо под диктовку и т. д.), дает повод надеяться, что мы сумеем провернуть подобный – всего лишь подобный – фокус, когда осуществим обратное проектирование мозга.
В таком случае, возможно, сходства мозга людей, говорящих по-французски, несмотря на все наблюдаемые анатомические различия, лучше всего объяснить на уровне виртуальной машины: все франкоговорящие люди имеют в голове ту или иную версию ФВМ, французской виртуальной машины, системы взаимосвязанных диспозиций, или микропривычек, каким-то образом хранящихся в миллиардах регистров мозга. Мозг русскоговорящих людей будет отличаться наличием подобной системы надежных шаблонов, РВМ. Если сказать франкоговорящему человеку: Donnez-moi le sel, s’il vous plait, – ФВМ гарантированно проконтролирует то же самое поведение, которое у русскоговорящего человека можно вызвать посредством введения в РВМ в его голове следующих данных: “Передай мне соль, пожалуйста”. Как же создаются ФВМ и РВМ, которые функционируют в нашем мозге?
Мы пока не знаем, как описать разные уровни активности мозга людей, играющих в шахматы или говорящих по-французски. Несомненно, не стоит и надеяться на появление подробной схемы наподобие той, что позволяет программистам создавать свои творения на высшем уровне, имея полную уверенность, что компилятор (программа, которая берет инструкции высшего уровня и преобразует их в код, понятный аппаратному обеспечению) выдаст работающую программу. Но теперь у нас есть прекрасный экспериментальный образец: мы знаем по крайней мере один способ объяснить высокоуровневые способности машины с триллионами подвижных частей, не прибегая к концепции чудо-ткани.