
Глава 14
УПРАВЛЕНИЕ РАСПРЕДЕЛЕННЫМИ ПРОЦЕССАМИ
14.1. Миграция процессов
14.2. Распределенные глобальные состояния
14.3. Распределенные взаимоисключения
14. 4. Распределенная взаимоблокировка
14.5. Резюме, ключевые термины и контрольные вопросы
14.6. Рекомендуемая литература
14.7. Задачи
В этой главе изучаются основные механизмы, используемые в распределенных в операционных системах. Сначала рассматривается перемещение (миграция) процессов, которое состоит в переносе активного процесса с одной машины на другую; затем исследуется, как процессы, выполняющиеся в разных системах и управляемые каждый своими локальными часами, могут координировать свою деятельность при обмене информацией с некоторой задержкой. Наконец, в последней части главы изучаются два вопроса, играющие важную роль в управлении распределенными процессами: взаимоисключение и взаимоблокировка.
14.1. Миграция процессов
Перенос (миграция) процесса состоит в передаче с одной машины на другую информации о состоянии процесса, достаточной для того, чтобы выполнение процесса можно было продолжить на новой машине. Первоначально интерес к этой концепции возник благодаря исследованиям методов выравнивания загрузки нескольких соединенных в сеть систем; в настоящее время применение данной концепции распространилось за пределы этой области.
Раньше среди большого количества работ, посвященных распределению нагрузки, было мало таких, в основе которых лежала надлежащая реализация переноса процессов, включающая возможность вытеснения процесса на одной машине и возобновления его через некоторое время на другой. Как показал опыт, такой перенос процесса с вытеснением возможен, хотя при этом возникают накладные расходы, гораздо большие, чем по предварительным оценкам [ARTS89a]. Некоторые исследователи считают, что из-за этих затрат переносы процессов непрактичны. Однако подобные оценки оказались слишком пессимистичными. Новые реализации, включая те, которые были воплощены в коммерческих продуктах, способствовали дальнейшему развитию этой области; ее обзор представлен в данном разделе.
Обоснование
Перенос процессов в распределенных системах необходим по ряду причин [SMIT88, JUL88], включая следующие.
- Распределение нагрузки. Перенося процессы с более загруженных систем на менее загруженные, можно выравнивать загрузку систем, что будет способствовать повышению общей производительности. Эмпирические данные свидетельствуют о том, что таким образом можно достичь существенного роста производительности [LELA86, CABR86]. Однако алгоритмы распределения нагрузки должны быть тщательно разработаны. В [EAGE86] отмечено, что чем интенсивнее происходит обмен информацией в распределенной системе, тем хуже становится ее производительность. Обсуждение этого во проса со ссылками на другие источники можно найти в [ESKI90].
- Производительность обмена информацией. Процессы, интенсивно обменивающиеся информацией, можно перенести на один узел, чтобы снизить стоимость передачи данных и длительность взаимодействия. Кроме того, если процесс выполняет анализ данных, которые находятся в файле или наборе файлов, размер которого превышает размер процесса, возможно, лучше перенести процесс к данным, а не наоборот.
- Работоспособность. Может возникнуть необходимость перенести выполняющийся в течение длительного времени процесс, чтобы избежать запланированного простоя или отказов, о возможности возникновения которых стало известно заранее. Если от операционной системы поступило подобное извещение, процесс, которому нужно продолжать свою работу, может либо перейти на другую систему, либо убедиться, что позже его можно будет перезапустить на этой же системе.
- Использование особых возможностей. Процесс может переместиться с целью использования уникальных аппаратных или программных возможностей конкретного узла.
Механизмы переноса процессов
Разрабатывая средство переноса процессов, следует обращать внимание на ряд вопросов, в число которых входят следующие.
- Кто должен стать инициатором переноса?
- Какая "часть" процесса должна быть перенесена?
- Что должно произойти с необработанными сообщениями и сигналами?
Инициация переноса
Выбор инициатора переноса зависит от предназначения переноса процессов. Если целью является перераспределение нагрузки, то решение о необходимости переноса процесса должно приниматься модулем операционной системы, управляющим загрузкой систем. Этот модуль отвечает за вытеснение переносимых процессов или передачу им сигналов. Чтобы определить, куда нужно перенести процесс, модуль должен обмениваться информацией с подобными ему модулями из других систем и иметь возможность отслеживать загрузку этих систем. Если же целью является использование каких-то особых ресурсов, то при возникновении необходимости процесс может мигрировать самостоятельно. В этом случае процесс должен быть осведомлен о существовании распределенной системы; в предыдущем случае работа функции переноса процесса и существование нескольких систем могут остаться для процесса незаметными.
Что переносится
Во время переноса процесса необходимо "разобрать" его в старой системе и воссоздать в новой. Это не дублирование процесса, а его перемещение. Следовательно, необходимо перенести образ процесса, состоящий, по крайней мере, из управляющего блока. Кроме того, нужно обновить все связи, предназначенные для передачи сигналов и сообщений, между данным процессом и другими процессами. Эти требования проиллюстрированы на рис. 14.1. Процесс 3 перешел с машины S и стал процессом 4 на машине D. Идентификаторы всех содержащихся в процессе связей (они обозначены строчными буквами) остаются прежними. Ответственность за перенос управляющего блока процесса и обновление отображения связей возлагается на операционную систему. Перенос процесса остается незамеченным как самим процессом, так и его партнерами по обмену информацией.
Перенос управляющего блока процесса осуществляется просто. Сложность с точки зрения производительности представляет перенос адресного пространства процесса и открытых им файлов. Сначала рассмотрим адресное пространство процесса, предполагая, что используется схема виртуальной памяти (сегментация и/или разбивка на страницы). Можно рассмотреть такие стратегии [MILO96].
- Интенсивная (полная). Во время переноса процесса перемещается все адресное пространство. Этот подход, несомненно, является самым понятным, В старой системе не остается никаких следов процесса. Однако если адресное пространство очень большое и процессу вряд ли понадобится большая его часть, то можно избежать его полного перемещения, тем самым на порядок сократив расходы по переносу процесса.
- Предварительное копирование. Пока процесс продолжает выполняться на старом узле, его адресное пространство копируется на новый узел. Страницы, которые были изменены на старой системе во время предварительного копирования, нужно скопировать еще раз. Такая стратегия сокращает время простоя процесса, возникающего при его переносе.
- Интенсивная (выборочная). Осуществляется перенос только тех страниц адресного пространства, которые находятся в основной памяти и были изменены. Все остальные блоки виртуального адресного пространства переносятся только по мере необходимости. Это сводит к минимуму передачу данных. Однако при соблюдении такой стратегии нужно, чтобы машина, с которой переносится процесс, продолжала принимать участие в его работе, поддерживая элементы таблицы страниц и/или сегментов, а также осуществляя удаленное предоставление страниц.
- Копирование по запросу. Эта стратегия является разновидностью предыдущей. В данном случае страницы предоставляются только тогда, когда на них поступает запрос. При этом начальные затраты на перенос процесса являются минимальными (в пределах от десятых до сотых долей микросекунды).
- Очистка, Страницы процесса удаляются из основной памяти старой машины и переносятся на диск. После этого доступ к ним осуществляется непосредственно с диска старого узла, без участия его основной памяти. Такая стратегия избавляет от необходимости держать в основной памяти старого узла какие-либо страницы переносимого процесса, освобождая занимаемыйим блок памяти для других процессов.
Одна из трех последних стратегий может понадобиться в том случае, если процессу при работе на новой машине, скорее всего, не понадобится большая часть его адресного пространства (например, если он переносится на новую машину только на время, чтобы поработать с каким-то файлом, и скоро вернется). С другой стороны, если через некоторое время после переноса процесса на новую машину будет осуществлен доступ к большей части его адресного пространства, то частичный перенос блоков адресного пространства может оказаться менее эффективным, чем простой перенос всего адресного пространства, при котором используются первые две стратегии.
Во многих случаях заранее неизвестно, понадобится ли большая часть отсутствующего в основной памяти адресного пространства. Однако если процессы разбиты на потоки и если основной единицей переноса является не процесс, а поток, то наиболее привлекательно выглядит стратегия, основанная на удаленной подкачке страниц. Этой стратегии почти всегда отдается предпочтение, потому что оставшиеся потоки процесса остаются на старой системе и им также требуется доступ к адресному пространству этого процесса. Перенос потоков реализован в операционной системе Emerald [JUL89].
Аналогично можно рассматривать и перенос открытых файлов. Если первоначально файл находится в той же системе, что и переносимый процесс, и если файл заблокирован переносимым процессом для своего исключительного использования, то имеет смысл перенести файл вместе с процессом. При этом возникает опасность, состоящая в том, что перенос процесса может быть лишь временным, и в течение пребывания процесса на новой системе файл ему может не понадобиться. Поэтому, возможно, стоит переносить весь файл только после того, как переносимый процесс обратится к нему. Если файл используется совместно с другими распределенными процессами, то следует поддерживать распределенный доступ к этому файлу без перемещения.
Если разрешено использовать кэш, как это происходит в системе Sprite (см. рис. 13.7), то возникают дополнительные сложности. Например, если процесс открыл файл для записи, затем разветвился, а затем один из его дочерних процессов оказался перенесенным на другую машину, то этот файл теперь должен быть открыт для записи с двух различных узлов. В алгоритме совместимости кэшей, применяющемся в операционной системе Sprite, запрещено кэширование файла, если с ним работают процессы, выполняющиеся на двух разных машинах [DOUG89, DOUG91].
Сигналы и сообщения
И, наконец, рассмотрим, что происходит с сигналами и сообщениями, адресованными переносимому процессу. Происходящее зависит от механизма временного хранения необработанных сигналов и сообщений, обеспечивающего их сохранность в течение процесса переноса, а затем направляющего их по новому адресу. Может возникнуть необходимость в течение некоторого времени поддерживать такой канал передачи информации, чтобы убедиться, что все необработанные сообщения и сигналы достигли пункта конечного назначения.
Сценарий переноса
В качестве показательного примера самопроизвольного переноса рассмотрим средство, предоставляемое операционной системой AIX фирмы IBM [WALK89], являющейся распределенной системой UNIX. Подобное средство имеется и в операционной системе LOCUS [POPE85], которая фактически послужила основой для разработки системы AIX. Кроме того, это средство было перенесено в операционную систему OSF/1 AD, в которой оно получило название TNC [ZAJC93].
События развиваются по такому сценарию.
1. Когда процесс решает, что ему нужно перейти на другую машину, он выбирает ее и отправляет туда сообщение об удаленном создании задания. Вместе с сообщением переносится часть образа процесса, а также информация об открытых файлах.
2. На принявшей сообщение машине процесс ядра порождает дочерний процесс, которому передается эта информация.
3. Новый процесс получает данные, аргументы или информацию из стека — все, что нужно для его работы. Если код программы находится в основной памяти в измененном, по сравнению с дисковым, состоянии, то он копируется из памяти; в противном случае копирование осуществляется из глобальной файловой системы.
4. Исходный процесс получает сигнал о завершении переноса, после чего отправляет новому процессу завершающее сообщение и самоуничтожается.
Если инициатором переноса процесса послужил другой процесс, события развиваются аналогично. Принципиальное отличие состоит в том, что переносимый процесс должен быть приостановлен и должен переноситься в невыполняющемся состоянии. Эта процедура соблюдается, например, в операционной системе Sprite [DOUG89].
В приведенном выше сценарии перенос процесса происходит динамично, включая различные действия по переносу образа процесса. Если же перенос процесса не является самопроизвольным, а его инициатором выступает другой процесс, возможен другой подход, описанный в [SMIT89]. При таком подходе образ процесса и все его адресное пространство копируется в файл, процесс уничтожается, файл с помощью соответствующего средства передачи копируется на другую машину, а затем процесс воссоздается из файла на новой машине.
Согласование переноса
Другой аспект миграции процессов связан с принятием решения о переносе. В некоторых случаях это решение является односторонним. Например, если перенос происходит с целью выравнивания нагрузки, то предназначенный для этого управляющий модуль отслеживает относительную нагрузку, приходящуюся на различные машины, и при необходимости осуществляет перенос. Если самопроизвольный перенос используется для того, чтобы процесс мог получить доступ к особым средствам или к большим удаленным файлам, то решение о переносе может принять сам процесс. Однако в некоторых распределенных системах в принятии подобного решения может принимать участие система, на которую собирается перейти процесс. Одной из причин этого является желание сохранить время отклика на запросы пользователя на прежнем уровне. Предположим, например, что пользователь выполняет некоторые операции на рабочей станции. Если какие-то процессы будут перенесены в его систему, то время ее отклика может заметно вырасти, даже если такой перенос выполнен с целью выравнивания нагрузки.
Примером механизма согласования переноса процесса может послужить механизм, встречающийся в операционной системе Charlotte [FINK89, ARTSSOb]. Стратегией переноса ведает служебная программа Starter, которая принимает решения о том, какой процесс подлежит переносу, когда и куда его нужно переносить. Эта служебная программа реализована в виде процесса, который, кроме того, несет ответственность за долгосрочное планирование и за распределение памяти, и поэтому она может координировать стратегии сразу в трех областях. Каждый процесс программы Starter может управлять кластером машин. Starter регулярно получает от ядра довольно подробную статистику о загрузке каждой машины кластера.
Решение о переносе должно приниматься совместно двумя процессами программы Starter, один из которых выполняется на исходном узле, а другой — на узле назначения (рис. 14.2). При этом выполняются такие шаги.
1. Starter, управляющий исходной системой S, принимает решение о целесообразности переноса процесса Р в какую-то другую систему D. Он отправляет процессу Starter в системе D сообщение с запросом на перенос.
2. Если Starter системы D готов принять новый процесс, он отвечает согласием.
3.Starter системы S передает это решение ядру своей системы с помощью вызова сервиса (если он выполняется на системе S) или с помощью сообщения, которое отправляется процессу KernJob (KJ) машины S (если данный программный стартер выполняется на другой машине). KJ — это процесс, который используется для преобразования сообщений, поступивших от удаленных процессов, в вызовы сервисов.
4. Затем ядро машины S формирует предложение по поводу пересылки процесса системе D. Это предложение включает в себя статистику процесса Р (его возраст, загрузку процессора и интенсивность обмена информацией).
5. Если в системе D недостаточно ресурсов, она может отклонить предложение. В противном случае ядро системы D передает это предложение своей программе Starter, которая получает всю информацию, поступившую от системы S.
6. Система D извещается о решении, принятом в результате выполнения соответствующего алгоритма программы Starter, с помощью вызова Migrateln.
7. В системе D выделяются необходимые ресурсы в целях избежания взаимоблокировок и проблем, связанных с управлением потоками, после чего система S извещается о том, что ее процесс будет принят.
На рис. 14.2 показаны два других процесса, А и В, которые имеют открытые связи с процессом Р. После выполнения описанных выше действий машина 1, на которой находится система S, должна отправить машинам 0 и 2 сообщение о необходимости обновления связей, чтобы сохранить связи процесса Р с процессами А и В. В этом сообщении указывается новый адрес каждой связи, содержащейся в процессе Р. В целях синхронизации ядра-адресаты должны ответить подтверждением. После этого все сообщения, соответствующие любой из связей процесса Р, пересылаются непосредственно в систему D. Обмен сообщениями, выполняющийся с целью обновления связей, может выполняться параллельно с описанными выше шагами. Наконец, после выполнения шага 7 и после обновления всех связей система S собирает весь контекст процесса Р в одно сообщение и пересылает это сообщение системе D.
Машина 4 тоже работает под управлением операционной системы Charlotte, но она не принимает участия в переносе процесса и поэтому не обменивается информацией с другими системами на протяжении этого отрезка времени.
Вытеснение
Механизм согласования позволяет системе назначения отказаться от переноса в одностороннем порядке. Кроме того, было бы полезно позволить системе вытеснять процессы, перенесенные на нее. Например, на простаивающую рабочую станцию могут быть перенесены несколько процессов. Как только пользователь этой рабочей станции начнет выполнять на ней какие-то операции, может возникнуть необходимость вытеснить с рабочей станции перешедшие на нее процессы, чтобы обеспечить адекватное время отклика.
Возможности вытеснения продемонстрированы в операционной системе Sprite [DOUG89]. В этой системе, предназначенной для рабочих станций, все выглядит так, как будто каждый процесс на протяжении всего своего времени жизни выполняется на одном и том же узле, который называется домашним узлом процесса. Если процесс переносится на другую машину, он становится внешним процессом на этой машине. Машина в любой момент времени может вытеснить внешний процесс, вследствие чего он переносится на свой домашний узел.
Механизм вытеснения операционной системы Sprite состоит из таких элементов.
1. Управляющий процесс на каждом узле отслеживает его текущую загрузку, чтобы определить, когда можно принять новые внешние процессы. Если этот процесс обнаруживает активность консоли рабочей станции, он приступает к процедуре вытеснения всех внешних процессов.
2. Вытесняемый процесс возвращается на домашний узел. Если освобождается какой-нибудь другой узел, процесс может перейти на него.
3. Хотя вытеснение всех процессов занимает некоторое время, все предназначенные для вытеснения процессы немедленно приостанавливаются. Если позволить процессу, ожидающему своего вытеснения, продолжить работу, это сократит время, в течение которого процесс остается замороженным, но снизит вычислительные мощности узла, вовлеченные в процесс вытеснения.
4. Все адресное пространство вытесняемого процесса передается на домашний узел. Затраты времени на вытеснение процесса и его возвращение на домашний узел, можно было бы существенно уменьшить, восстанавливая образ памяти вытесняемого процесса из внешнего узла, на котором он находился до этого, но не сразу, а по мере надобности. Однако при этом внешний узел будет вынужден предоставлять вытесняемому процессу свои ресурсы и сервисы в течение более длительного периода времени, чем необходимо.
Вытесняющие и невытесняющие переносы
Данный раздел рассматривает вытесняющий перенос процессов, который включает передачу частично выполненного процесса (или, по крайней мере, процесса, создание которого уже завершено). Невытесняющий перенос процессов — более простая функция, работающая только с процессами, выполнение которых еще не началось, благодаря чему переносить информацию о состоянии процесса не требуется. В обоих случаях необходимо передать на удаленный узел информацию о среде, в которой будет выполняться процесс. Сюда могут входить сведения о текущем каталоге пользователя, унаследованных процессом привилегиях и унаследованных ресурсах, таких, как дескрипторы файлов.
Невытесняющий перенос процесса может быть полезен при балансировке нагрузки (см., например, [SHIV92]). Она обладает тем преимуществом, что позволяет избежать накладных затрат на полный перенос процесса. Недостатком этой схемы является то, что она не может адекватно реагировать на внезапные изменения в распределении нагрузки.