Главная страница Взаимодействие нетривиальных процессов При выполнении той же программы в Digital Unix 4.0В получим: alpha % mqcreate -m 256 -z 2048 /tmp/bigq alpha Is -1 /tmp/bigq -rw-r--r-- 1 rstevens system 537288 Oct 25 15:38 /tmp/bigq В этой реализации размер очереди соответствует максимальному количеству сообщений и максимальному размеру сообщения (256 х 2048 = 524 288), а оставшиеся 13 ООО байт дают возможность хранить 48 байт добавочной информации для каждого сообщения (48x256) и еще 712 байт. 5.4. Функции mq send и mq receive Эти две функции предназначены для помещения сообщений в очередь и получения их оттуда. Каждое сообщение имеет свой приоритет, который представляет собой беззнаковое целое, не превышающее MQ PRIO MAX. Стандарт Posix требует, чтобы эта величина была не меньше 32. ПРИМЕЧАНИЕ - В Solaris 2.6 значение MQ PRIO MAX равняется именно 32, но в Digital Unix 4.0В этот предел равен уже 256. В листинге 5.7 мы покажем, как получить эти значения. Функция mq recei ve всегда возвращает старейшее в указанной очереди сообщение с максимальным приоритетом, и приоритет может быть получен вместе с содержимым сообщения и его длиной. ПРИМЕЧАНИЕ- Действие mq receive отличается от действия msgrcv в System V (раздел 6.4). Сообщения System V имеют поле type, аналогичное по смыслу приоритету, но для функции msgrcv можно указать три различных алгоритма возвращения сообщений: старейшее сообщение в очереди, старейшее сообщение с указанным типом или старейшее сообщение с типом, не превышающим указанного значения. #include <mqueue.h> int mq send(mqd t mqdes. const char *ptr. sizej len. unsigned int prio): I* Возвращает 0 в случае успешного завершения. -1 - в случае возникновения ошибок */ ssize t mq receive(mqd t mqdes. char *ptr. size t len. unsigned int *prlop): /* Возвращает количество байтов в сообщении в случае успешного завершения. -1 - в случае ошибки */ Первые три аргумента обеих функций аналогичны первым трем аргументам функций wri te и read соответственно. ПРИМЕЧАНИЕ- Объявление указателя на буфер как char* кажется ошибкой - тип void* больше соответствовал бы по Rvxv ппочим 6vHKuHflM Posix.l. ветствовал бы по духу прочим функциям Posix.l. Значение аргумента len функции mq recei ve должно быть по крайней мере не меньше максимального размера сообщения, которое может быть помещено в очередь, то есть значения поля mq msgsize структуры mq attr для этой очереди. Если len оказывается меньше этой величины, немедленно возвращается ошибка EMSGSIZE. ПРИМЕЧАНИЕ- Это означает, что большинству приложений, использующих очереди сообщений Posix, придется вызывать mq getattr после открытия очереди для определения максимального размера сообщения, а затем выделять память под один или несколько буферов чтения этого размера. Требование, чтобы буфер был больше по размеру, чем максимально возможное сообщение, позволяет функции mq receive не возвращать уведомление о том, что размер письма превышает объем буфера. Сравните это, например, с флагом MSG N0ERR0R и ошибкой E2BIG для очередей сообщений System V (раздел 6.4) и флагом MSG TRUNC для функции recvmsg, используемой с дейтаграммами UDP (раздел 13.5 [24]). Аргумент/>по устанавливает приоритет сообщения для mq sencl, его значение должно быть меньше MQ PRIO MAX. Если при вызове mq receive priop является ненулевым указателем, в нем сохраняется приоритет возвращаемого сообщения. Если приложению не требуется использование различных приоритетов сообщений, можно указывать его равным нулю для mq sencl и передавать mq recei ve нулевой указатель в качестве последнего аргумента. ПРИМЕЧАНИЕ- Разрешена передача сообщений нулевой длины. Это тот случай, когда важно не то, о чем говорится й стандарте (Posix.l), а то, о чем в нем не говорится: нигде не запрещена передача сообщений нулевой длины. Функция mq receive возвращает количество байтов в сообщении (в случае успешного завершения работы) или -1 в случае возникновения ошибок, так что О обозначает сообщение нулевой длины. Очередям сообщений Posix и System V не хватает полезной функции: получатель не может определить отправителя сообщения. Эта информация могла бы пригодиться многим приложениям. К сожалению, большинство механизмов передачи сообщений IPC не позволяют определить отправителя сообщений. В разделе 15.5 мы расскажем, как эта возможность обеспечивается для дверей. В разделе 14.8 [24] описано, как эта возможность обеспечивается в BSD/OS для доменных сокетов Unix. В разделе 15.3.1 [21] описано, как SVR4 передает информацию об отправителе по каналу при передаче по нему дескриптора. В настоящее время методы BSD/OS широко используются, и хотя реализация SVR4 является частью стандарта Unix 98, она требует передачи дескриптора по каналу, что обычно является более дорогостоящей операцией, чем просто передача данных. Мы не можем предоставить отправителю возможность передать информацию о себе (например, эффективный идентификатор пользователя) в самом сообщении, поскольку мы не можем быть уверены, что эта информация окажется истинной. Хотя разрешения доступа к очереди сообщений определяют, имеет ли право отправитель помещать в нее сообщения, это все равно не дает однозначности. Существует возможность создавать одну очередь для каждого отправителя (о которой рассказывается в связи с очередями System V в разделе 6.8), но это плохо подходит для больших приложений. Наконец, если функции для работы с очередями сообщений реализованы как пользовательские функции (как мы показываем в разделе 5.8), а не как часть ядра, мы не можем доверять никакой информации об отправителе, передаваемой с сообщением, так как ее легко подделать. Пример: программа mqsend в листинге 5.5 приведен текст программы, помещающей сообщение в очередь. Листинг 5.5. Программа mqsend pxmsg/mqsend.c 1 #include unpipc.h 2 int 3 mainCint argc. char **argv) 5 mqd t mqd: 6 void *ptr: 7 size t len: 8 uint t prio: 9 if (argc !- 4) 10 err quit( usage: mqsend <name> <#bytes> <priority> ): 11 len = atoi(argv[2]); 12 prio - atoi(argv[3]): 13 mqd = Mq open(argv[l]. 0 WRONLY); 14 ptr = CallocClen. sizeof (char)): 15 Mq send(mqd. ptr. len. prio): 16 exitCO): 17 } И размер сообщения, и его приоритет являются обязательными аргументами командной строки. Буфер под сообщение вьщеляется функцией call ос, которая инициализирует его нулем. Пример: программа mqreceive Программа в листинге 5.6 считывает сообщение из очереди. Листинг 5.6. Программа mqreceive pxmsg/mqreceive.c 1 #include unpipc.h 2 int 3 mainCint argc, char **argv) 5 int c. flags: 6 mqd t mqd; 7 ssize t n; 8 uint t prio; 9 void *buff: 10 struct mq attr attr; 11 flags = 0 RDONLY; 12 while С Cc = GetoptCargc. argv, n )) != -1) { 13 switch Cc) { 14 case n: 15 flags 1= OJONBLOCK; 16 break: 17 } продолжен! -S
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |