Э. Таненбаум, М. ван Стеен - Распределённые системы (принципы и парадигмы) (1162619), страница 51
Текст из файла (страница 51)
Эти девять комбинаций иллюстрируеттабл. 3.2. Используются следующие сокращения:4 GR — организовать глобальную ссылку;"¥ MV — перенести ресурс;4- СР — копировать значение ресурса;-¥ RB — выполнить новую привязку процесса к локальному ресурсу.Таблица 3 . 2 . Варианты переноса кода на другую машинуПривязка ресурса к машинеПривязкаресурсак процессуПривязкапо идеитификаторуПривязкапо значениюПривязкапо типуНеприсоединенный ресурсСвязанныйресурсФиксированныйресурсМ\/(илиОР)GR (или MV)GRСР(илиМ\/, GR)ОЯ(илиСР)GRRB (или MV, СР)RB (или GR, СР)RB (или GR)Рассмотрим сначала возможности, возникающие при привязке процесса к ресурсу по идентификатору.
Если ресурс неприсоединенный, лучше всего перене-196Глава 3. Процессысти его на другую машину вместе с кодом. Однако если этот ресурс используетсяпереносимым процессом совместно с другими, следует организовать на него глобальную ссылку — ссылку, которая в состоянии будет преодолеть границу между машинами. Примером такой ссылки может быть URL. Если ресурс связанныйили фиксированный, организация глобальной ссылки также является наилучшим решением проблемы.Важно, что реалргзация системы глобальных ссылок может быть сложнее простого использования URL и иногда оказывается слишком дорогостоящей. Рассмотрим, например, программу обработки высококачественных изображений наотдельной рабочей станции. Создание в реальном времени высококачественныхизображений — это задача, требующая интенсивных вычислений, поэтому программа может быть перенесена на высокопроизводительный вычислительныйсервер. Организация глобальных ссылок на рабочую станцию будет означать организацию связи между сервером и рабочей станцией.
Кроме того, серьезная обработка, происходящая одновременно на сервере и рабочей станции, потребуетсоблюденрш определенных требований к скорости передачи изображений. В результате может оказаться, что перенос программы на вычислительный сервер неоправдан просто потому, что цена поддержания глобальных ссылок чересчур высока.Другим примером трудностей с поддержанием глобальных ссылок можетбыть перенос процесса, использующего локальную конечную точку взаимодействия. В этом случае мы имеем дело с фиксированными ресурсами, привязанными к процессу по идентификатору, поэтому имеется два основных решения.
Одно из них состоит в том, чтобы позволить процессу после переноса установитьсоединение с исходной машиноР!, создав там отдельный поток выполнения, который просто будет перенаправлять все приходящие сообщения на новое «местожительства» процесса. Основным недостатком такого подхода является то, чтопри сбоях или повреждении исходной машины связь с перенесенным процессомбудет прервана.
Другое решение состоит в том, чтобы, взяв все процессы, связанные с перенесенным, поменять их глобальные ссылки и пересылать сообщенияна новую конечную точку взаимодействия целевой машины.Другая ситуация возникает в случае привязке! по значению. Рассмотрим сначала фиксированные ресурсы. Комбинация фиксированных ресурсов и привязкипо значению возможна, например, в случае использования процессом участка памяти совместно с другими процессами.
Организация глобальных ссылок в этомслучае может потребовать от нас реализации распределенной разделяемой памяти, о которой мы говорили в главе 1. Однако чаще всего подобное решение неприемлемо.Связанные ресурсы, ссылка на которые производится по значению, — это чаще всего библиотеки времени исполнения. Обычно допускается копированиеэтих ресурсов на другую машину, причем это копирование может быть осуществлено до переноса кода. Организация глобальных ссылок может оказаться хорошей альтернативой копированию в том случае, если нужно скопировать большой объем данных, например словари и тезаурусы текстового редактора.3.4.
Перенос кода197Наиболее простой случай — неприсоединенные ресурсы. Наилучшее решениепри этом — скопировать (или переместить) ресурсы в новое место, исключая варианты, когда они совместно используются несколькими процессами. В последнем случае единственным выходом будет создание глобальных ссылок.Последний вариант — привязка по типу. Независимо от способа привязки ресурса к машине решение состоит в новой привязке процесса к локальным ресурсам того же типа. Только в том случае, если ресурсы данного типа на локальноймашине отсутствуют, мы можем скопировать или переместить оригинальные ресурсы на новое место или организовать глобальные ссылки на них.3.4.3.
Перенос кода в гетерогенных системахРанее мы предполагали, что перенесенный код может быть с легкостью выполненна целевой машине. Это предположение относилось исключительно к гомогенным системам. Обычно, однако, распределенные системы создаются из набора гетерогенных платформ, каждая из которых имеет свою собственную машиннуюархитектуру и операционную систему. Перенос в подобных системах требует,чтобы поддерживались все эти платформы, то есть сегмент кода должен выполняться на всех этих платформах без перекомпиляции текста программы.
Крометого, мы должны быть уверены, что сегмент исполнения на каждой из этих платформ будет представлен правильно.Проблемы могут быть частично устранены в том случае, если мы ограничимся слабой мобильностью. В этом случае обычно не суш.ествует такой информации времени исполнения, которую надо было бы передавать от машины к машине.Это означает, что достаточно скомпилировать исходный текст программы, создав различные варианты сегмента кода — по одному на каждую потенциальнуюплатформу.В случае сильной мобильности основной проблемой, которую надо будет решить, является перенос сегмента исполнения.
Проблема заключается в том, чтоэтот сегмент в значительной степени зависит от платформы, на которой выполняется задача. На самом деле перенести сегмент исполнения, не внося в него никаких изменений, можно только в том случае, если машина-приемник имеет туже архитектуру и работает под управлением той же операционной системы.Сегмент исполнения содержит закрытые данные процесса, его текущий стеки счетчик программы.
Стек обычно содержит временные данные, такие как значения локальных переменных, но может также содержать и информацию, зависящую от платформы, например значения регистров. Важно отметить, что еслибы нам удалось избавиться от данных, зависящих от платформы, то перенестисегмент на другую машину и продолжить исполнение там было бы значительнопроще.Решение, работающее в случае процедурных языков, таких как С или Java,показано на рис. 3.10. Перенос кода ограничен несколькими конкретными моментами выполнения программы.
Точнее, перенос возможен только в моментвызова очередной подпрограммы. Под подпрограммой имеется в виду функцияв С, метод в Java и т. п. Исполняющая система создает собственную копию про-198Глава 3. Процессыграммного стека, причем машинно-независимую. Мы будем называть эту копиюстеком переноса {migration stack). Стек переноса обновляется при вызове подпрограммы или возвращении управления из подпрограммы.При вызове подпрограммы исполняющая система выполняет маршалинг данных, которые были помещены в стек во время предыдущего вызова. Эти данныепредставляют собой значения локальных переменных, а также значения параметров текущего вызова процедуры.
Данные после маршалинга помещаютсяв стек переноса вместе с идентификатором вызванной подпрограммы. Кроме того,в стек переноса помещается адрес (в форме метки перехода), с которого должнопродолжаться исполнение после возвращения из подпрограммы.ЛокальныеПомещение параметровоперации вызова после их маршалингастека Вв стек переносаЛокальныепеременныепроцедуры ВМетка возврата(перехода)в процедуру Аиз процедуры ВВызов _В из А "Значенияпараметровпроцедуры ВИдентификацияпроцедуры ВЛокальныепеременныепроцедуры АМетка возвратав процедуру,вызвавшуюпроцедуру АЗначенияпараметровпроцедуры АПрограммныйстекИдентификацияпроцедуры АСтек переноса(данные толькопосле маршалинга)Рис.
3.10. Принцип работы стека переноса, поддерживающего переноссегмента исполнения в гетерогенных средахЕсли перенос кода происходит в точке вызова подпрограммы, исполняющаясистема производит сначала маршалинг всех глобальных данных программы, составляющих сегмент исполнения. Данные, специфичные для данной машины,и текущий стек игнорируются. Данные после маршалинга и стек переноса передаются на ожидающую их машину. Кроме того, на машину-приемник загружает-3.4.
Перенос кода199ся соответствующий сегмент кода, содержащий подходящие для ее архитектурыи операционной системы код. На машине-приемнике выполняется демаршалингполученных данных сегмента исполнения, и из стека переноса формируется новый стек исполнения. После этого исполнение может быть продолжено простымвходом в подпрограмму, которая была вызвана на исходном сайте.Ясно, что подобный подход возможен только в том случае, если компиляторгенерирует код для обновления стека переноса при каждом входе в подпрограмму или выходе из нее. Компилятор должен также генерировать в вызывающемкоде метки, позволяющие реализовать выход из подпрограммы в виде переходов(машинно-независимых). Кроме того, мы нуждаемся в подходящей исполняющей системе.
Тем не менее существует множество систем, успешно использующих подобную технологию. Так, в [127] показано, как можно обеспечить переноспрограмм, написанных на C/C++, в гетерогенных системах путем небольших изменений в языках, используя для добавления кода поддержки стека переноса исключительно директивы препроцессора.Проблемы переноса кода, вызванные гетерогенностью, во многих случаяхсходны с проблемами переносимости.
Не будет неожиданностью то, что такжесходны и методы их решения. Так, например, в конце 70-х годов было предложено простое решение, позволившее решить множество проблем с переносом языкаPascal на различные машины. Таким решением стала генерация промежуточногомашинно-независимого кода для абстрактной виртуальной машины [40]. Эта машина, разумеется, требовала реализации на множестве различных платформ,благодаря которой программы на языке Pascal могли работать на них всех.