Читать «UNIX: взаимодействие процессов» онлайн - страница 98

Уильям Ричард Стивенс

9    case 'e':

10    oflag |= IPC_EXCL;

11    break;

12   }

13  }

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 = %ld\n", 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