^?
solaris % msgrcv –n –t999/tmp/test1
msgrcv error: No message of desired type
solaris % grep desired /usr/include/sys/errno.h
#define ENOMSG 35 /* No message of desired type */
solaris % msgrmid /tmp/test1
Сначала мы вызываем ipcs, чтобы убедиться, что очередь пуста, а затем помещаем в нее сообщение длиной 1 байт с типом 100. Затем мы запрашиваем сообщение с типом 999, и программа блокируется (при вызове msgrcv), ожидая помещения в очередь сообщения с указанным типом. Мы прерываем ожидание нажатием клавиши. Затем мы запускаем программу с флагом –n, предотвращающим блокировку, и видим, что в этом случае возвращается ошибка с кодом ENOMSG. После этого мы удаляем очередь с помощью программы msgrmid. Мы могли бы удалить очередь и с помощью системной команды
solaris % ipcrm –q 100
в которой указывается идентификатор очереди, или с помощью той же команды в другом формате
solaris % ipcrm –Q 0x113e
где указывается ключ очереди сообщений.
Программа msgrcvid
Покажем теперь, что для получения доступа к очереди сообщений System V не обязательно вызывать msgget: все, что нужно, — это знать идентификатор очереди сообщений, который легко получить с помощью ipcs, и считать разрешения доступа для очереди. В листинге 6.6 приведен упрощенный вариант программы msgrcv из листинга 6.4.
Здесь мы уже не используем msgget. Вместо этого используется идентификатор очереди сообщений, являющийся обязательным аргументом командной строки.
//svmsg/msgrcvid.c
1 #include "unpipc.h"
2 #define MAXMSG (8192 + sizeof(long))
3 int
4 main(int argc, char **argv)
5 {
6 int mqid;
7 ssize_t n;
8 struct msgbuf *buff;
9 if (argc != 2)
10 err_quit("usage: msgrcvid
11 mqid = atoi(argv[1]);
12 buff = Maloc(MAXMSG);
13 n = Msgrcv(mqid, buff, MAXMSG, 0, 0);
14 printf("read %d bytes, type = %ld\n", n, buff->mtype);
15 exit(0);
16 }
Вот пример использования этой программы:
solaris % touch /tmp/testid
solaris % msgcreate /tmp/testid
solaris % msgsnd /tmp/testid4 400
solaris % ipcs –qo
IPC status from
T ID KEY MODE OWNER GROUP CBYTES QNUM
Message Queues:
q 150 0x0000118a –rw-r--r-- rstevens other1 4 1
solaris % msgrcvid 150
read 4 bytes, type = 400
Идентификатор очереди (150) мы узнали с помощью ipcs, его мы и предоставляем программе msgrcvid в качестве аргумента командной строки.
Этот же метод можно использовать для семафоров System V (упражнение 11.1) и разделяемой памяти System V (упражнение 14.1).
6.7. Пример программы клиент-сервер
Перепишем наш пример программы типа клиент-сервер из раздела 4.2 с использованием двух очередей сообщений. Одна из очередей предназначена для передачи сообщений от клиента серверу, а другая — в обратную сторону.
Заголовочный файл svmsg.h приведен в листинге 6.7. Мы подключаем наш стандартный заголовочный файл и определяем ключи для каждой из очередей сообщений.
//svmsgcliserv/svmsg.h
1 #include "unpipc.h"
2 #define MQ_KEY1 1234L
3 #define MQ_KEY2 2345L
Функция main для сервера приведена в листинге 6.8. Программа создает обе очереди сообщений, и не беда, если какая-нибудь из них уже существует, потому что мы не указываем флаг IPC_EXCL. Функция server дана в листинге 4.16. Она вызывает наши собственные функции mesgsend и mesgrecv, новые версии которых будут приведены ниже.
//svmsgcliserv/server_main.с
1 #include "svmsg.h"
2 void server(int, int);
3 int
4 main(int argc, char **argv)
5 {
6 int readid, writeid;