Читаем Архитектура операционной системы UNIX полностью

Рассмотрим программу, представленную на Рисунке 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), ядро обрезает сообщение, возвращает запрошенное количество байт и удаляет сообщение из списка целиком.

#include ‹sys/types.h›

#include ‹sys/ipc.h›

#include ‹sys/msg.h›

#define MSGKEY 75

struct msgform {

 long mtype;

 char mtext[256];

};

main() {

 struct msgform msg;

 int msgid, pid, *pint;

 msgid = msgget(MSGKEY, 0777);

 pid = getpid();

 pint = (int *) msg.mtext;

 *pint = pid; /* копирование идентификатора процесса в область текста сообщения */

 msg.mtype = 1;

 msgsnd(msgid, &msg, sizeof(int), 0);

 msgrcv(msgid, &msg, 256, pid, 0);

 /* идентификатор процесса используется в качестве типа сообщения */

 printf("клиент: получил от процесса с pid %d\n", *pint);

}

Рисунок 11.6. Пользовательский процесс

алгоритм msgrcv /* получение сообщения */

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

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

 (2) адрес массива, в который заносится сообщение

 (3) размер массива

 (4) тип сообщения в запросе

 (5) флаги

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

{

 проверить права доступа;

loop:

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

 /* найти сообщение, нужное пользователю */

 if (тип сообщения в запросе == 0)

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

 else

if (тип сообщения в запросе › 0)

    рассмотреть первое сообщение в очереди, имеющее данный тип;

  else /* тип сообщения в запросе ‹ 0 */

   рассмотреть первое из сообщений в очереди с наименьшим значением типа при условии, что его тип не превышает абсолютное значение типа, указанного в запросе;

 if (сообщение найдено) {

Перейти на страницу:

Все книги серии Серия книг по программному обеспечению издательства prentice hall

Похожие книги