Стивенс Уильям Ричард
Шрифт:
6.2. Функция msgget
Создать новую очередь сообщений или получить доступ к существующей можно с помощью функции msgget:
Возвращаемое значение представляет собой целочисленный идентификатор, используемый тремя другими функциями msg для обращения к данной очереди. Идентификатор вычисляется на основе указанного ключа, который может быть получен с помощью функции ftok или может представлять собой константу IPC_PRIVATE, как показано на рис. 3.1.
Флаг oflag представляет собой комбинацию разрешений чтения-записи, показанную в табл. 3.3. К разрешениям можно добавить флаги IPC_CREAT или IPC_CREAT | IPC_EXCL с помощью логического сложения, как уже говорилось в связи с рис. 3.2.
При создании новой очереди сообщений инициализируются следующие поля структуры msqid_ds:
■ полям uid и cuid структуры msg_perm присваивается значение действующего идентификатора пользователя вызвавшего процесса, а полям gid и cgid — действующего идентификатора группы;
■ разрешения чтения-записи, указанные в oflag, помещаются в msg_perm.mode;
■ значения msg_qnum, msg_lspid, msg_lrpid, msg_stime и msg_rtime устанавливаются в 0;
■ в msg_ctime записывается текущее время;
■ в msg_qbytes помещается системное ограничение на размер очереди.
6.3. Функция msgsnd
После открытия очереди сообщений с помощью функции msgget можно помещать сообщения в эту очередь с помощью msgsnd.
Здесь msqid представляет собой идентификатор очереди, возвращаемый msgget. Указатель ptr указывает на структуру следующего шаблона, определенного в <sys/ msg.h>:
Тип сообщения должен быть больше нуля, поскольку неположительные типы используются в качестве специальной команды функции msgrcv, о чем рассказывается в следующем разделе.
Название mtext в структуре msgbuf употреблено не вполне правильно; данные в сообщении совсем не обязательно должны быть текстом. Разрешена передача любых типов данных как в двоичном, так и в текстовом формате. Ядро никак не интерпретирует содержимое сообщения.
Для описания структуры мы используем термин «шаблон», поскольку ptr указывает на целое типа long, представляющее собой тип сообщения, за которым непосредственно следует само сообщение (если его длина больше 0 байт). Большинство приложений не пользуются этим определением структуры msgbuf, поскольку установленного в ней количества данных (1 байт) обычно недостаточно для прикладных задач. На количество данных в сообщении никаких ограничений при компиляции не накладывается (как правило, оно может быть изменено системным администратором), поэтому вместо объявления структуры с большим объемом данных (большим, чем поддерживается текущей реализацией) определяется этот шаблон. Большинство приложений затем определяют собственную структуру сообщений, в которой передаваемые данные зависят от нужд этих приложений.
Например, если приложению нужно передавать сообщения, состоящие из 16-разрядного целого, за которым следует 8-байтовый массив символов, оно может определить свою собственную структуру так:
Аргумент length функции msgsnd указывает длину сообщения в байтах. Это длина пользовательских данных, следующих за типом сообщения (целое типа long). Длина может быть и 0. В указанном выше примере длина может быть вычислена как sizeof(Message) – sizeof(long).
Аргумент flag может быть либо 0, либо IPC_NOWAIT. В последнем случае он отключает блокировку для msgsnd: если для нового сообщения недостаточно места в очереди, возврат из функции происходит немедленно. Это может произойти, если:
■ в данной очереди уже имеется слишком много данных (значение msg_qbytes в структуре msqid_ds);
■ во всей системе имеется слишком много сообщений.
Если верно одно из этих условий и установлен флаг IPC_NOWAIT, функция msgsnd возвращает ошибку с кодом EAGAIN. Если флаг IPC_NOWAIT не указан, а одно из этих условий выполняется, поток приостанавливается до тех пор, пока не произойдет одно из следующего: