Сетевые операционные системы

       

Отправка и получение сообщений


Конечной целью создания портов является возможность отправки в них сообщений. В этом разделе поясняется, как сообщения отправляются, как получаются и что они содержат. Mach поддерживает один системный вызов для отправки и получения сообщений. Этот вызов содержится внутри библиотечной процедуры, называемой mach_mes. Она имеет семь параметров и большое количество опций. Чтобы дать представление о ее сложности, нужно отметить, что существует 35 различных кодов возврата ошибочных ситуаций. Ниже дается упрощенный обзор некоторых возможностей этой процедуры. К счастью, она используется в функциях, генерируемых чаще компилятором заглушек (stub compiler), а не вручную.

Итак, вызов mach_mes используется и для отправки и для получения сообщений. Он может отослать сообщение в порт, а затем вернуть управление вызвавшей mach_mes функции немедленно, так что она может модифицировать буфер сообщения, не влияя на посланные данные. Он может также использоваться для попытки получения сообщения из порта, причем, если порт пуст, он либо блокирует вызвавшую нить, либо отказывается от попытки по истечении некоторого тайм-аута. Наконец, можно объединять операции отправки и получения, сначала отсылая сообщение, а затем блокируя нить до получения ответа. В последнем режиме вызов mach_mes можно использовать для реализации RPC.

Типичный вызов функции mach_mes выглядит так:

mach_mes( &hdr, options, send_size, rcv_size, rcv_port, timeout, notify_port);

Первый параметр, hdr, является указателем на сообщение, которое нужно отослать или на место, куда нужно поместить приходящее сообщение, или на то и другое. Сообщение начинается с фиксированного заголовка, непосредственно за которым следует тело сообщения. Эта структура показана на рисунке 6.11.

Детали формата сообщения будут рассмотрены ниже, а сейчас необходимо отметить, что заголовок содержит имя права доступа для порта назначения. Эта информация нужна ядру, так как ядро из нее узнает о том, куда нужно отправить сообщение. Когда выполняется операция только ПОЛУЧИТЬ, заголовок не заполняется, так как он будет полностью переписан пришедшим сообщением.


Второй параметр, options, содержит бит, определяющий, что сообщение должно быть отправлено, и другой бит, который говорит о том, что оно должно быть получено. Если оба бита включены, то выполняется RPC. Еще один бит разрешает тайм-аут, величина которого указана в параметре timeout в миллисекундах. Если требуемая операция не может быть выполнена за время тайм-аута, то вызов возвращает код ошибки. Если часть ПОСЛАТЬ вызова RPC не выполняется за отведенное время (например, порт назначения заполнен в течение слишком большого времени), то часть ПОЛУЧИТЬ просто не выполняется.



Рис. 6.11. Формат сообщения Mach

Остальные биты поля options позволяет операции ПОСЛАТЬ, которая не может завершиться немедленно, вернуть управление, а сообщение о статусе завершения посылается на notify_port позже.

Параметры send_size и rcv_size определяют длину отсылаемого сообщения и количество байт, отводимых для хранения приходящего сообщения, соответственно. Rcv_port используется для приема сообщений. Это имя прав доступа порта или набора портов, которые должны получить сообщение.

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

Поле Размер сообщения указывает общую длину заголовка и тела сообщения. Эта информация нужна как передающей, так и принимающей сторонам.

Далее идут имена двух мандатов доступа (то есть индексы в списке прав доступа передающей стороны). Первый относится к порту назначения, а второй - к порту ответа.

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


Это назначение может измениться в будущем.

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

Следует упомянуть о некоторых вопросах, связанных с приемом сообщений. Во-первых, что делать, если поступившее сообщение имеет длину больше, чем длина буфера? Предусмотрено два варианта: удалить это сообщение или же вернуть вместе с кодом ошибки данный размер, чтобы позволить вызвавшей функцию mach_mes нити повторить передачу с буфером большего размера.

Если существует несколько нитей, блокированных на операции ПОЛУЧИТЬ из одного и того же порта, и сообщение поступает в порт, то системой выбирается одна из них для получения сообщения. Остальные остаются блокированными.


Содержание раздела