read-write: 664, cbytes = 1, qnum = 1, qbytes = 4096
IPC status from running system as of MOn Oct 20 15:36:49 1997
T ID Key MODE OWNER GROUP
Message Queues:
q 1150 00000000 –rw-rw-r-- rstevens other1
Выведенные значения соответствуют ожидаемым. Нулевое значение ключа обычно соответствует IPC_PRIVATE, как мы отмечали в разделе 3.2. В этой системе на очередь сообщений накладывается ограничение по объему в 4096 байт. Поскольку мы записали сообщение с 1 байтом данных и msg_cbytes имеет значение 1, это ограничение накладывается на объем полезных данных и не включает тип сообщения (long), указываемый для каждого сообщения.
6.6. Простые примеры
Поскольку очереди сообщений System V обладают живучестью ядра, мы можем написать несколько отдельных программ для работы с этими очередями и изучить их действие.
Программа msgcreate
В листинге 6.2 приведена программа msgcreate, создающая очередь сообщений.
9-12 Параметр командной строки –e позволяет указать флаг IPC_EXCL.
16 Полное имя файла, являющееся обязательным аргументом командной строки, передается функции ftok. Получаемый ключ преобразуется в идентификатор функцией msgget.
//svmsg/msgcreate.c
1 #include "unpipc.h"
2 int
3 main(int argc, char **argv)
4 {
5 int c, oflag, mqid;
6 oflag = SVMSG_MODE | IPC_CREAT;
7 while ((c = Getopt(argc, argv, "e")) != –1) {
8 switch (c) {
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. Эта функция инициализирует буфер нулем.
//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), поэтому мы определим свою собственную константу.
//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");