Полезное в сети

Всегда в теме

Статистика


Яндекс.Метрика


Онлайн всего: 1
Гостей: 1
Пользователей: 0

Рекомендуем



Главная » Статьи » Операционные системы » Общее

Механизм передачи сообщений в распределенных системах
Единственным по-настоящему важным отличием распределенных систем от централизованных является способ взаимодействия между процессами. Принципиально межпроцессное взаимодействие может осуществляться одним из двух способов:
 с помощью совместного использования одних и тех же данных (разделяемая память);
 путем передачи друг другу данных в виде сообщений.
В централизованных системах связь между процессами, как правило, предполагает наличие разделяемой памяти. Типичный пример — задача «поставщик-потребитель». В этом случае один процесс пишет в разделяемый буфер, а другой читает из него. Даже наиболее простая форма синхронизации — семафор — требует, чтобы хотя бы одно слово (переменная самого семафора) было разделяемым. Аналогичным образом происходит взаимодействие не только между пользовательскими процессами, но и между приложением и операционной системой — процесс в пользовательском режиме запрашивает у ОС выполнения некоторой операции с помощью системного вызова, помещая в доступную ему часть оперативной памяти параметры этого системного вызова (например, имя файла, смещение от его начала и количество байт, которые необходимо прочитать). После этого модуль ядра ОС считывает эти параметры из пользовательской памяти (ядру в привилегированном режиме доступна вся память, как ее системная часть, так и пользовательская) и выполняет системный вызов. Взаимодействие и в этом случае происходит за счет непосредственно доступной обоим участникам области памяти.
В распределенных системах не существует памяти, непосредственно доступной процессам, работающим на разных компьютерах, поэтому взаимодействие процессов (как находящихся в пользовательской фазе, так и в системной, то есть выполняющих код операционной системы) может осуществляться только путем передачи сообщений через сеть. Как было показано в разделе «Сетевые службы и сетевые сервисы» главы 2 «Назначение и функции операционной системы», на основе механизма передачи сообщений работают все сетевые службы, предоставляющие пользователям сети разнообразные услуги — доступ к удаленным файлам, принтерам, почтовым ящикам и т. п. В сообщениях переносятся запросы от клиентов некоторой службы к соответствующим серверам — например, запрос на просмотр содержимого определенного каталога файловой системы, расположенной на сетевом сервере. Сервер возвращает ответ — набор имен файлов и подкаталогов, входящих в данный каталог, также помещая его в сообщение и отправляя его по сети клиенту.
Сообщение — это блок информации, отформатированный процессом-отправителем таким образом, чтобы он был понятен процессу-получателю. Сообщение состоит из заголовка, обычно фиксированной длины, и набора данных определенного типа переменной длины. В заголовке, как правило, содержатся следующие элементы.
 Адрес — набор символов, уникально определяющих отправляющий и получающий процессы. Адресное поле, таким образом, состоит из двух частей — адреса процесса-отправителя и адреса процесса-получателя. Адрес каждого процесса может, в свою очередь, иметь некоторую структуру, позволяющую найти нужный процесс в сети, состоящей из большого количества компьютеров.
 Последовательный номер, являющийся идентификатором сообщения. Используется для идентификации потерянных сообщений и дубликатов сообщений в случае отказов в сети.
 Структурированная информация, состоящая в общем случае из нескольких частей: поля типа данных, поля длины данных и поля значения данных (то есть собственно данных). Поле типа данных определяет, например, что данные являются целым числом или же представляют собой строку символов (это поле может также содержать признак нерезидентности данных, то есть указатель на данные, которые хранятся где-то вне данного сообщения). Второе поле определяет длину передаваемых в сообщении данных (обычно в байтах), то есть размер следующего поля сообщения. Сообщение может включать несколько элементов, состоящих из описанных трех полей. В тех случаях, когда сообщение всегда переносит данные одного и того же типа, поле типа может быть опущено. То же касается поля длины данных — для тех типов сообщений, которые переносят данные фиксированного формата, но такая ситуация характерна только для протоколов низкого уровня (например, ATM, имеющего фиксированный размер поля данных в 48 байт).
В любой сетевой ОС имеется подсистема передачи сообщений, называемая также транспортной подсистемой, которая обеспечивает набор средств для организации взаимодействия процессов по сети. Назначение этой системы — экранировать детали сложных сетевых протоколов от программиста. Подсистема позволяет процессам взаимодействовать посредством достаточно простых примитивов. В самом простом случае системные средства обеспечения связи могут быть сведены к двум основным коммуникационным примитивам, один send (отправить) — для посылки сообщения, другой recei ve (получить) — для получения сообщения. В дальнейшем на их базе могут быть построены более мощные средства сетевых коммуникаций, такие как распределенная файловая система или служба вызова удаленных процедур, которые, в свою очередь, также могут служить основой для работы других сетевых служб.
Транспортная подсистема сетевой ОС имеет обычно сложную структуру, отражающую структуру семиуровневой модели взаимодействия открытых систем (Open System Interconnection, OSI)1. Представление сложной задачи сетевого взаимодействия компьютеров в виде иерархии нескольких частных задач позволяет организовать это взаимодействие максимально гибким образом. В то же время каждый уровень модели OSI экранирует особенности лежащих под ним уровней от вышележащих уровней, что делает средства взаимодействия компьютеров все более универсальными по мере продвижения вверх по уровням. Таким образом, в процесс выполнения примитивов send и receive вовлекаются средства всех нижележащих коммуникационных протоколов (рис. 9.3).
1 Более подробно с моделью OSI и функциями ее уровней можно ознакомится в приложе-! нии. Структура сетевых средств ОС обсуждалась также в разделе «Многослойная модель .-.подсистемы ввода-вывода» главы 7 «Ввод-вывод и файловая система».

Рис. 9.3. Примитивы обмена сообщениями и транспортные средства подсистемы ввода-вывода
Несмотря на концептуальную простоту примитивов send и receive, существуют различные варианты их реализации, от правильного выбора которых зависит эффективность работы сети. В частности, эффективность зависит от способа задания адреса получателя. Не менее важны при реализации примитивов передачи сообщений ответы и на другие вопросы. В сети всегда имеется один получатель или их может быть несколько? Требуется ли гарантированная доставка сообщений? Должен ли отправитель дождаться ответа на свое сообщение, прежде чем продолжать свою работу? Как отправитель, получатель и подсистема передачи сообщений должны реагировать на отказы узла или коммуникационного канала во время взаимодействия? Что нужно делать, если приемник не готов принять сообщение, нужно ли отбрасывать сообщение или сохранять его в буфере? А если сохранять, то как быть, если буфер уже заполнен? Разрешено ли приемнику изменять порядок обработки сообщений в соответствии с их важностью? Ответы на подобные вопросы составляют семантику конкретного протокола передачи сообщений.
Синхронизация
Центральным вопросом взаимодействия процессов в сети является способ их синхронизации, который полностью определяется используемыми в операционной системе коммуникационными примитивами. В этом отношении коммуникационные примитивы делятся на блокирующие (синхронные) и неблокирующие (асинхронные), причем смысл данных терминов в целом соответствует смыслу аналогичных терминов, применяемых при описании системных вызовов (см. подраздел «Системные вызовы» раздела «Мультипрограммирование на основе прерываний» в главе 4 «Процессы и потоки») и операций ввода-вывода (см. подраздел «Поддержка синхронных и асинхронных операций ввода-вывода» раздела «Задачи ОС по управлению файлами и устройствами» в главе 7 «Ввод-вывод и файловая система»). В отличие от локальных системных вызовов (а именно такие системные вызовы были рассмотрены в главах 4 и 7) при выполнении коммуникационных примитивов завершение запрошенной операции в общем случае зависит не только от некоторой работы локальной ОС, но и от работы удаленной ОС.
Коммуникационные примитивы могут быть оформлены в операционной системе двумя способами: как внутренние процедуры ядра ОС (в этом случае ими могут использоваться только модули ОС) или как системные вызовы (доступные в этом случае процессам в пользовательском режиме).
При использовании блокирующего примитива send процесс, выдавший запрос на его выполнение, приостанавливается до момента получения по сети сообщения-подтверждения о том, что приемник получил отправленное сообщение. А вызов блокирующего примитива receive приостанавливает вызывающий процесс до момента, когда он получит сообщение. При использовании неблокирующих примитивов send и receive управление возвращается вызывающему процессу немедленно, сразу после того, как ядру передается информация о том, где в памяти находится буфер, в который нужно поместить сообщение, отправляемое в сеть или ожидаемое из сети. Преимуществом этой схемы является параллельное выполнение вызывающего процесса и процедур передачи сообщения (не обязательно работающих в контексте вызвавшего соответствующий примитив процесса).
Важным вопросом при использовании неблокирующего примитива receive является выбор способа уведомления процесса-получателя о том, что сообщение пришло и помещено в буфер. Обычно для этой цели требуется один из двух способов.
 Опрос (polling). Этот метод предусматривает наличие еще одного базового примитива test (проверить), с помощью которого процесс-получатель может анализировать состояние буфера.
 Прерывание (interrupt). Этот метод использует программное прерывание для уведомления процесса-получателя о том, что сообщение помещено в буфер. Хотя такой метод и очень эффективен (он исключает многократные проверки состояния буфера), у него имеется существенный недостаток — усложненное программирование, связанное с прерываниями пользовательского уровня, то есть прерываниями, по которым вызываются процедуры пользовательского режима (например, вызов процедур АРС в ОС Windows NT по завершении операции ввода-вывода, рассмотренный в главе 8 «Дополнительные возможности файловых систем»).
При использовании блокирующего примитива send может возникнуть ситуация, когда процесс-отправитель блокируется навсегда. Например, если процесс получатель потерпел крах или же отправленное сообщение было утеряно из-за сетевой ошибки. Чтобы предотвратить такую ситуацию, блокирующий примитив send часто использует механизм тайм-аута. То есть определяется интервал времени, после которого операция send завершается со статусом «ошибка». Механизм тайм-аута может использоваться также блокирующим примитивом receive для предотвращения блокировки процесса-получателя на неопределенное время, когда процесс-отправитель потерпел крах или сообщение было потеряно вследствие сетевой ошибки.
Если при взаимодействии двух процессов оба примитива — send и receive — являются блокирующими, говорят^ что процессы взаимодействуют по сети синхронно (рис. 9.4), в противном случае взаимодействие считается асинхронным

По сравнению с асинхронным взаимодействием синхронное является более простым, его легко реализовать. Оно также более надежно, так как гарантирует процессу-отправителю, возобновившему свое выполнение, что его сообщение было получено. Главный же недостаток — ограниченный параллелизм и возможность возникновения клинчей.
Обычно в ОС имеется один из двух видов примитивов, но ОС является более гибкой, если поддерживает как блокирующие, так и неблокирующие примитивы.
Буферизация в примитивах передачи сообщений
При передаче сообщений могут возникнуть ситуации, когда принимающий процесс оказывается не готовым обработать сообщение при его прибытии, но для процесса было бы желательным, чтобы операционная система на время сохранила поступившее сообщение в буфере для последующей обработки.
Способ буферизации тесно связан со способом синхронизации процессов при обмене сообщениями. При использовании синхронных, то есть блокирующих примитивов, можно вообще обойтись без буферизации сообщений операционной системой. При этом возможны два варианта организации работы примитивов. В первом случае процесс-отправитель подготавливает сообщение в своей памяти и обращается к примитиву send, после чего процесс блокируется. Операционная система отправителя ждет, когда процесс-получатель выполнит на своем компьютере примитив receive, в результате чего ОС получателя направит служебное сообщение-подтверждение готовности к приему основного сообщения. После получения такого подтверждения ОС на компьютере-отправителе разблокирует процесс-отправитель и тот немедленно после этого пошлет сообщение по сети. Процесс-получатель после обращения к примитиву receive также переводится своей ОС в состояние ожидания, из которого он выходит при поступлении сообщения по сети. Сообщение немедленно копируется ОС в память процесса-получателя, не требуя буферизации, так как процесс ожидает его прихода и готов к его обработке.
Буферизация не требуется и при другом варианте обмена сообщениями, когда процесс-отправитель посылает сообщение в сеть, не дожидаясь прихода от получателя подтверждения о готовности к приему. Затем процесс-отправитель блокируется либо до прихода такого подтверждения (в этом случае никакой дополнительной работы с данным сообщением не выполняется), либо до истечения тайм-аута, после которого сообщение посылается вновь, причем в случае многократных повторных неудачных попыток сообщение отбрасывается.
В обоих случаях сообщение непосредственно из памяти процесса-отправителя попадает в сеть, а после прихода из сети — в память процесса-получателя, минуя буфер, поддерживаемый системой. Однако такая организация на практике в сетевых операционных системах не применяется, так как в первом варианте процесс-получатель может достаточно долго ждать, пока сообщение будет передано по сети (в большой составной сети, например в Интернете, задержки могут достигать нескольких секунд), а во втором — из-за неготовности процесса-получателя сообщение может многократно бесполезно передаваться по сети, засоряя каналы связи.
Именно поэтому при использовании синхронных примитивов все же предусматривают буферизацию. При этом буфер, как правило, выбирается размером в одно сообщение, так как процесс-отправитель не может послать следующее сообщение, не получив подтверждения о приеме предыдущего. Сообщение помещается в буфер, поддерживаемый операционной системой компьютера-получателя, если в момент его прихода процесс-получатель не может обработать сообщение немедленно, например из-за того, что процесс либо не является текущим, либо не готов к приему сообщения, так как не обратился к примитиву receive. Буфер может располагаться как в системной области памяти, так и в области памяти пользовательского процесса, в любом случае буфером управляет операционная система, модули которой получают сообщения по сети.
Для всех вариантов обмена сообщениями с помощью асинхронных примитивов необходима буферизация. Поскольку при асинхронном обмене процесс-отправитель может посылать сообщение всегда, когда ему это требуется, не дожидаясь подтверждения от процесса-получателя, для исключения потерь сообщений требуется буфер неограниченной длины. Так как буфер в реальной системе всегда имеет ограниченный размер, то могут возникать ситуации с переполнением буфера и на них нужно каким-то образом реагировать. Для уменьшения вероятности потерь сообщений степень асинхронности процесса обмена сообщениями обычно ограничивается механизмом управления потоком сообщений. Управление потоком заключается в том, что при заполнении буфера на принимающей стороне до некоторого опасного порога процесс-передатчик блокируется до тех пор, пока процесс-приемник не обработает часть принятых сообщений и не разгрузит буфер до безопасной величины. Конечно, вероятность потерь сообщений из-за переполнения буфера все равно сохраняется, например из-за того, что служебное сообщение о необходимости приостановки передачи сообщений может быть потеряно сетью. Асинхронный обмен с управлением потоком — это наиболее сложный способ организации обмена сообщениями, так как для повышения эффективности, то есть максимизации скорости обмена и минимизации потерь, он требует применения сложных алгоритмов приостановки и возобновления процесс передачи, например таких, которые применяются в протоколе TCP.
Обычно операционная система предоставляет для прикладных процессов специальный примитив для создания буферов сообщений. Такого рода примитив, назовем его, например, create_buffer (создать буфер), процесс должен использовать перед тем, как отправлять или получать сообщения с помощью примитивов send и receive. При создании буфера его размер может либо устанавливаться по умолчанию, либо выбираться прикладным процессом. Часто такой буфер носит название порта (port), или почтового ящика {mailbox).
При реализации схем буферизации сообщений необходимо также решить вопрос о том, что должна делать операционная система с поступившими сообщениями, для которых буфер не создан. Такая ситуация может возникнуть в том случае, когда примитив send на одном компьютере выполнен раньше, чем примитив create_buffer на другом. Каким образом ядро на компьютере получателя сможет узнать, какому процессу адресовано вновь поступившее сообщение, если имеется несколько активных процессов? И как оно узнает, куда его скопировать?
Один из вариантов — просто отказаться от сообщения в расчете на то, что отправитель после тайм-аута передаст сообщение повторно и к этому времени получатель уже создаст буфер. Этот подход не сложен в реализации, но, к сожалению, отправитель (или скорее ядро его компьютера) может сделать несколько таких безуспешных попыток. Еще хуже то, что после достаточно большого числа безуспешных попыток ядро отправителя может сделать неправильный вывод об аварии на машине получателя или о неправильности его адреса.
Второй подход к этой проблеме заключается в том, чтобы хранить хотя бы некоторое время поступающие сообщения в ядре получателя в расчете на то, что вскоре будет выполнен соответствующий примитив create_buffer. Каждый раз, когда поступает такое «неожидаемое» сообщение, включается таймер. Если заданный временной интервал истекает раньше, чем происходит создание буфера, то сообщение теряется.
Хотя этот метод и уменьшает вероятность потери сообщений, он порождает проблему хранения и управления преждевременно поступившими сообщениями. Необходимы буферы, которые следует где-то размещать, освобождать, то есть которыми нужно как-то управлять, что создает дополнительную нагрузку на операционную систему.
Категория: Общее | Добавил: Wrecker (24.04.2012)
Просмотров: 3870 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Поиск

Вход

Гость
  • Вход
  • Регистрация
  • Читаемое

    Заходи не жди