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