next up previous contents
Next: Синхронизация Up: Программирование с помощью DIPC Previous: Удаленное выполнение программ   Contents

Обмен данными

Большинство программ принимают некие данные, обрабатывают их соответствующими способами и выдают результаты. ``Легкость'' обмена данными в распределенных системах очень важна. В рамках DIPC вы можете использовать для этих целей сообщения или сегменты разделяемой памяти. Разделяемая память - это асинхронный механизм. Программа может получить к ней доступ, когда ``пожелает''. При этом может возникнуть длинная задержка между временем предоставления доступа и временем действительного приема данных. Программа ничего этого ``не замечает''. Сообщения являются очень доступным способом передачи данных. Вы можете передать только те данные, которые захотите, и к тому же - только нужному процессу. Такой коммуникационный стиль называется стилем ``один - одному''. Сообщения можно представить как синхронный способ обмена данными. Программа приостанавливается системным вызовом msgrcv() до тех пор, пока другой процесс не прибегнет к вызову msgsnd(). Программист должен сам решать, какой из двух приведенных методов нужно использовать.

Каждая страница разделяемой распределенной памяти может
иметь одновременно несколько читателей на различных компьютерах, но для нее может быть только один компьютер с процессом-писателем. Если DIPC сконфигурирована с поддержкой режима посегментной передачи, то сказанное применимо для сегмента целиком. Это значит, что читатели могут иметь ``разделяемую'' память (страницы) в своей локальной памяти и, следовательно, свободно ей пользоваться; но запись в одну из ``копий'' приведет к недостоверности данных на других машинах. Чтобы можно было продолжить чтение, содержимое памяти должно быть снова передано другим машинам. Если DIPC сконфигурирована с поддержкой режима посегментной передачи, то внутренний контекст разделяемого сегмента данных передается по сети. Если же процессы пользуются различными частями разделяемой памяти, вы должны установить постраничный режим передачи для DIPC, - чтобы программы, соответствующие процессам на различных компьютерах, могли адекватно читать страницы разделяемой памяти и записывать в них.

Каждый может применять режим постраничной передачи для увеличения эффективности пересылок данных: чтение всей требующейся информации из сегмента разделяемой памяти, выполнение всех необходимых обработок в локальной памяти и, наконец, размещение результатов, возможно, в иной разделяемой памяти. Разделяемая память рассматривается как ``дверь'' к другим машинам. Пока вы не пользуетесь сегментом разделяемой памяти, то не будете использовать и сеть.

Рассмотрим возможный сценарий использования разделяемой памяти при режиме посегментной передачи. Главный процесс запускается и размещает входные данные в разделяемой памяти. Затем запускаются другие удаленные процессы, которые могут читать данный разделяемый сегмент. Может одновременно быть несколько читателей, причем читать они могут также одновременно. Кроме того, поскольку одно содержимое сегмента пересылается каждой машине, то вероятность возникновения перегрузки при передачах будет невелика. (Это имеет смысл, только если удаленные процессы нуждаются во всех данных из разделяемого сегмента памяти). После обработки входных данных удаленные задачи могут вернуть результаты в тот же или другой сегмент разделяемой памяти, но могут использовать и сообщения. Так как писатель для разделяемой памяти может быть только один, то каждой удаленной машине рекомендуется предоставлять персональный сегмент для возвращения результатов. Таким образом можно организовать параллелизм. Следует напомнить, что DIPC можно использовать, и не придерживаясь рассмотренных выше указаний, но производительность может снизиться.

Постраничный режим передачи DIPC можно применять для того, чтобы позволить процессам параллельно читать и записывать различные части одной и той же разделяемой памяти.

В большинстве случаев, распределенной программе не нужно ``знать'', где исполняется процесс, к тому же в DIPC нет способа, которым программист мог бы явно сослаться на специфический компьютер в сети. Это создает условия адресной ``независимости'' программ. Программист может использовать иные средства опознавания различных процессов. Например использовать поле mtype структуры msgbuf для записи идентификатора, представляющего процесс, или разместить подобную информацию в некотором заранее оговоренном месте разделяемой памяти. Это предоставляет программисту возможность применять логическую адресацию.

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

При использовании DIPC смысловая интерпретация данных и осуществление любого преобразования возлагаются на приложение. Но нужно найти способ точно установить, нужны ли преобразования форматов для различных машин. В случае с сообщениями, программист может использовать, например, первый байт для индикации типа исходной машины. Принимающий процесс может самостоятельно решить вопрос о преобразовании. В случае с разделяемой памятью все не так просто. Во время чтения разделяемой памяти или записи в нее процесс может быть приостановлен, содержимое разделяемой памяти передано некой машине отличного типа, данные подменены сгенерированными данными и позже переданы назад оригинальной машине. Все происходит ``прозрачно'' для программы. Однако нужно избрать способ информировать программу об этих событиях.

Информирование выполяется двумя прерываниями. Одно из них - DIPC_SIG_WRITER, второе - DIPC_SIG_READER. Если DIPC сконфигурирована с поддержкой их передачи, то первое передается, когда процесс еще только становится писателем (ранее он мог быть просто читателем или вообще не иметь связей с сегментом). При посегментном режиме передачи процесс ``знает'', что имеет эксклюзивный контроль над сегментом. Процесс, например, может записать идентификатор текущей архитектуры в первые байты сегмента и поместить произведенные им данные в разделяемую память. Второе прерывание посылается, когда процесс становится читателем сегмента (ранее он не пользовался его содержимым). Процесс, например, может проверить первые байты сегмента для того, чтобы установить, нужно ли делать какие-либо преобразования. Обратите внимание на то, что прерывание DIPC_SIG_READER генерируется, если данная машина предварительно была писателем, а теперь стала читателем, т.е. ее права доступа стали более ограниченными.

Только что описанные действия производить не очень удобно, если применяется режим постраничной передачи, так как нет способа передать сигналом какие-либо ``лишние'' параметры получателю. Следовательно, не представляется возможным сообщить процессу, какую именно страницу в настоящий момент он читает или записывает. Программист может помочь себе в разрешении таких ситуаций путем предназначения четко указанных секций разделяемой памяти для определенных нужд.

В любом случае, даже если программист специально запретил (через SIG_IGN) два упомянутых прерывания или системный администратор сконфигурировал DIPC без поддержки передачи прерываний, связанных с разделяемой памятью, программист должен быть всегда готов к обработке такой ситуации. Имеются в виду проверка значений, возвращаемых системными вызовами, и их перезапуск при необходимости.



2004-06-22