Читать «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 */