Читать интересную книгу UNIX: взаимодействие процессов - Уильям Стивенс

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 33 34 35 36 37 38 39 40 41 ... 128

14  if (optind != argc – 1)

15   err_quit("usage: msgcreate [ –e ] <pathname>");

16  mqid = Msgget(Ftok(argv[optind], 0), oflag);

17  exit(0);

18 }

Программа msgsnd

Программа msgsnd приведена в листинге 6.3. Она помещает в очередь одно сообщение заданной длины и типа.

Мы создаем указатель на структуру msgbuf общего вида, а затем выделяем место под реальную структуру (буфер записи) соответствующего размера, вызвав calloc. Эта функция инициализирует буфер нулем.

Листинг 6.3. Помещение сообщения в очередь System V

//svmsg/msgsnd.c

1  #include "unpipc.h"

2  int

3  main(int argc, char **argv)

4  {

5   int mqid;

6   size_t len;

7   long type;

8   struct msgbuf *ptr;

9   if (argc != 4)

10   err_quit("usage: msgsnd <pathname> <#bytes> <type>");

11  len = atoi(argv[2]);

12  type = atoi(argv[3]);

13  mqid = Msgget(Ftok(argv[1], 0), MSG_W);

14  ptr = Calloc(sizeof(long) + len, sizeof(char));

15  ptr->mtype = type;

16  Msgsnd(mqid, ptr, len, 0);

17  exit(0);

18 }

Программа msgrcv

В листинге 6.4 приведен текст программы msgrcv, считывающей сообщение из очереди. В командной строке может быть указан параметр –n, отключающий блокировку, а параметр –t может быть использован для указания типа сообщения в функции msgrcv.

2 Не существует простого способа определить максимальный размер сообщения (об этом и других ограничениях мы поговорим в разделе 6.10), поэтому мы определим свою собственную константу.

Листинг 6.4. Считывание сообщения из очереди System V

//svmsg/msgrcv.c

1  #include "unpipc.h"

2  #define MAXMSG (8192 + sizeof(long))

3  int

4  main(int argc, char **argv)

5  {

6   int c, flag, mqid;

7   long type;

8   ssize_t n;

9   struct msgbuf *buff;

10  type = flag = 0;

11  while ((c = Getopt(argc, argv, "nt:")) != –1) {

12   switch (c) {

13   case 'n':

14    flag |= IPC_NOWAIT;

15    break;

16   case 't':

17    type = atol(optarg);

18    break;

19   }

20  }

21  if (optind != argc – 1)

22   err_quit("usage: msgrcv [ –n ] [ –t type ] <pathname>");

23  mqid = Msgget(Ftok(argv[optind], 0), MSG_R);

24  buff = Malloc(MAXMSG);

25  n = Msgrcv(mqid, buff, MAXMSG, type, flag);

26  printf("read %d bytes, type = %ldn", n, buff->mtype);

27  exit(0);

28 }

Программа msgrmid

Для удаления очереди сообщений мы вызываем функцию msgctl с командой IPC_RMID, как показано в листинге 6.5.

Листинг 6.5. Удаление очереди сообщений System V

//svmsg/msgrmid.c

1  #include "unpipc.h"

2  int

3  main(int argc, char **argv)

4  {

5   int mqid;

6   if (argc != 2)

7    err_quit("usage: msgrmid <pathname>");

8   mqid = Msgget(Ftok(argv[1], 0), 0);

9   Msgctl(mqid, IPC_RMID, NULL);

10  exit(0);

11 }

Примеры

Теперь воспользуемся четырьмя только что написанными программами. Создадим очередь и поместим в нее три сообщения:

solaris % msgcreate /tmp/no/such/file

ftok error for pathname "tmp/no/such/file" and id 0: No such file or directory

solaris % touch /trap/test1

solaris % msgcreate /tmp/test1

solaris % msgsnd /tmp/test1 1 100

solaris % msgsnd /tmp/test1 2 200

solaris % msgsnd /tmp/test1 3 300

solaris % ipcs –qo

IPC status from <running system> as of Sat Jan 10 11:25:45 1998

T ID  KEY        MODE       OWNER    GROUP  CBYTES QNUM

Message Queues:

q 100 0х0000113e –rw-r--r-- rstevens other1 6      3

Сначала мы пытаемся создать очередь, используя имя несуществующего файла. Пример показывает, что файл, указываемый в качестве аргумента ftok, обязательно должен существовать. Затем мы создаем файл /tmp/test1 и используем его имя при создании очереди сообщений. После этого в очередь помещаются три сообщения длиной 1, 2 и 3 байта со значениями типа 100, 200 и 300 (вспомните рис. 6.1). Программа ipcs показывает, что в очереди находятся 3 сообщения общим объемом 6 байт.

Теперь продемонстрируем использование аргумента type при вызове msgrcv для считывания сообщений в произвольном порядке:

solaris % msgrcv –t 200 /tmp/test1

read 2 bytes, type = 200

solaris % msgrcv –t -300 /tmp/test1

read 1 bytes, type = 100

solaris % msgrcv /tmp/test1

read 3 bytes, type = 300

solaris % msgrcv –n /tmp/test1

msgrcv error: No message of desired type

В первом примере запрашивается сообщение с типом 200, во втором примере — сообщение с наименьшим значением типа, не превышающим 300, а в третьем — первое сообщение в очереди. Последний запуск msgrcv иллюстрирует действие флага IPC_NOWAIT.

Что произойдет, если мы укажем положительное значение типа, а сообщений с таким типом в очереди не обнаружится?

solaris % ipcs –qo

IPC status from <running system> as of Sat Jan 10 11:37:01 1998

T ID  KEY        MODE       OWNER    GROUP  CBYTES QNUM

Message Queues:

q 100 0x0000113e –rw-r--r-- rstevens other1 0      0

solaris % msgsnd /tmp/test1 1 100

solaris % msgrcv –t 999 /temp/test1

^? нажали клавишу прерывания выполнения программы

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. Вместо этого используется идентификатор очереди сообщений, являющийся обязательным аргументом командной строки.

Листинг 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 = %ldn", 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 ... 33 34 35 36 37 38 39 40 41 ... 128
На этом сайте Вы можете читать книги онлайн бесплатно русская версия UNIX: взаимодействие процессов - Уильям Стивенс.

Оставить комментарий