Литмир - Электронная Библиотека
Содержание  
A
A

11.2.1 Сообщения

С сообщениями работают четыре системных функции: msgget, которая возвращает (и в некоторых случаях создает) дескриптор сообщения, определяющий очередь сообщений и используемый другими системными функциями, msgctl, которая устанавливает и возвращает связанные с дескриптором сообщений параметры или удаляет дескрипторы, msgsnd, которая посылает сообщение, и msgrcv, которая получает сообщение.

Синтаксис вызова системной функции msgget:

msgqid = msgget(key, flag);

где msgqid — возвращаемый функцией дескриптор, а key и flag имеют ту же семантику, что и в системной функции типа "get". Ядро хранит сообщения в связном списке (очереди), определяемом значением дескриптора, и использует значение msgqid в качестве указателя на массив заголовков очередей. Кроме вышеуказанных полей, описывающих общие для всего механизма права доступа, заголовок очереди содержит следующие поля:

• Указатели на первое и последнее сообщение в списке;

• Количество сообщений и общий объем информации в списке в байтах;

• Максимальная емкость списка в байтах;

• Идентификаторы процессов, пославших и принявших сообщения последними;

• Поля, указывающие время последнего выполнения функций msgsnd, msgrcv и msgctl.

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

Для посылки сообщения процесс использует системную функцию msgsnd:

msgsnd(msgqid, msg, count, flag);

где msgqid — дескриптор очереди сообщений, обычно возвращаемый функцией msgget, msg — указатель на структуру, состоящую из типа в виде назначаемого пользователем целого числа и массива символов, count — размер информационного массива, flag — действие, предпринимаемое ядром в случае переполнения внутреннего буферного пространства.

алгоритм msgsnd /* послать сообщение */

входная информация:

 (1) дескриптор очереди сообщений

 (2) адрес структуры сообщения

 (3) размер сообщения

 (4) флаги

выходная информация: количество посланных байт

{

 проверить правильность указания дескриптора и наличие соответствующих прав доступа;

 do while (для хранения сообщения не будет выделено место) 
{

  if (флаги не разрешают ждать)
 return;

  sleep (до тех пор, пока место не освободится);

 }

 получить заголовок сообщения;

 считать текст сообщения из пространства задачи в пространство ядра;

 настроить структуры данных: выстроить очередь заголовков сообщений, установить в заголовке указатель на текст сообщения, заполнить поля, содержащие счетчики, время последнего выполнения операций и идентификатор процесса;

 вывести из состояния приостанова все процессы, ожидающие разрешения считать сообщение из очереди;

}

Рисунок 11.4. Алгоритм посылки сообщения

Ядро проверяет (Рисунок 11.4), имеется ли у посылающего сообщение процесса разрешения на запись по указанному дескриптору, не выходит ли размер сообщения за установленную системой границу, не содержится ли в очереди слишком большой объем информации, а также является ли тип сообщения положительным целым числом. Если все условия соблюдены, ядро выделяет сообщению место, используя карту сообщений (см. раздел 9.1), и копирует в это место данные из пространства пользователя. К сообщению присоединяется заголовок, после чего оно помещается в конец связного списка заголовков сообщений. В заголовке сообщения записывается тип и размер сообщения, устанавливается указатель на текст сообщения и производится корректировка содержимого различных полей заголовка очереди, содержащих статистическую информацию (количество сообщений в очереди и их суммарный объем в байтах, время последнего выполнения операций и идентификатор процесса, пославшего сообщение). Затем ядро выводит из состояния приостанова все процессы, ожидающие пополнения очереди сообщений. Если размер очереди в байтах превышает границу допустимости, процесс приостанавливается до тех пор, пока другие сообщения не уйдут из очереди. Однако, если процессу было дано указание не ждать (флаг IPC_NOWAIT), он немедленно возвращает управление с уведомлением об ошибке. На Рисунке 11.5 показана очередь сообщений, состоящая из заголовков сообщений, организованных в связные списки, с указателями на область текста.

Архитектура операционной системы UNIX (ЛП) - pic_106.png

Рисунок 11.5. Структуры данных, используемые в организации сообщений

Рассмотрим программу, представленную на Рисунке 11.6. Процесс вызывает функцию msgget для того, чтобы получить дескриптор для записи с идентификатором MSGKEY. Длина сообщения принимается равной 256 байт, хотя используется только первое поле целого типа, в область текста сообщения копируется идентификатор процесса, типу сообщения присваивается значение 1, после чего вызывается функция msgsnd для посылки сообщения. Мы вернемся к этому примеру позже.

Процесс получает сообщения, вызывая функцию msgrcv по следующему формату:

count = msgrcv(id, msg, maxcount, type, flag);

где id — дескриптор сообщения, msg — адрес пользовательской структуры, которая будет содержать полученное сообщение, maxcount — размер структуры msg, type — тип считываемого сообщения, flag — действие, предпринимаемое ядром в том случае, если в очереди сообщений нет. В переменной count пользователю возвращается число прочитанных байт сообщения.

Ядро проверяет (Рисунок 11.7), имеет ли пользователь необходимые права доступа к очереди сообщений. Если тип считываемого сообщения имеет нулевое значение, ядро ищет первое по счету сообщение в связном списке. Если его размер меньше или равен размеру, указанному пользователем, ядро копирует текст сообщения в пользовательскую структуру и соответствующим образом настраивает свои внутренние структуры: уменьшает счетчик сообщений в очереди и суммарный объем информации в байтах, запоминает время получения сообщения и идентификатор процесса-получателя, перестраивает связный список и освобождает место в системном пространстве, где хранился текст сообщения. Если какие-либо процессы, ожидавшие получения сообщения, находились в состоянии приостанова из-за отсутствия свободного места в списке, ядро выводит их из этого состояния. Если размер сообщения превышает значение maxcount, указанное пользователем, ядро посылает системной функции уведомление об ошибке и оставляет сообщение в очереди. Если, тем не менее, процесс игнорирует ограничения на размер (в поле flag установлен бит MSG_NOERROR), ядро обрезает сообщение, возвращает запрошенное количество байт и удаляет сообщение из списка целиком.

120
{"b":"96903","o":1}