Читать «UNIX: взаимодействие процессов» онлайн - страница 100
Уильям Ричард Стивенс
Здесь мы уже не используем msgget. Вместо этого используется идентификатор очереди сообщений, являющийся обязательным аргументом командной строки.
Листинг 6.6. Считывание из очереди сообщений System V с известным идентификатором
//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 <mqid>");
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 <running system> as of Wed Mar 25 09:48:28 1998
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. Мы подключаем наш стандартный заголовочный файл и определяем ключи для каждой из очередей сообщений.
Листинг 6.7. Заголовочный файл svmsg.h для программы клиент-сервер, использующей очереди сообщений
//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, новые версии которых будут приведены ниже.
Листинг 6.8. Функция main программы-сервера, использующей очереди сообщений
//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;
7 readid = Msgget(MQ_KEY1, SVMSG_MODE | IPC_CREAT);
8 writeid = Msgget(MQ_KEY2, SVMSG_MODE | IPC_CREAT);
9 server(readid, writeid);
10 exit(0);
11 }
Листинг 6.9. Функция main программы-клиента, использующей очереди сообщений
//svmsgcliserv/client_main.с
1 #include "svmsg.h"
2 void client(int, int);
3 int
4 main(int argc, char **argv)
5 {
6 int readid, writeid;
7 /* assumes server has created the queues */
8 writeid = Msgget(MQ_KEY1, 0);
9 readid = Msgget(MQ_KEY2, 0);
10 client(readid, writeid);
11 /* now we can delete the queues */