Скачиваний:
85
Добавлен:
12.05.2015
Размер:
913.92 Кб
Скачать

18.3. Функция msgsnd

После открытия очереди сообщений с помощью функции msgget можно помещать сообщения в эту очередь с помощью msgsnd.

#include <sys/msg.h>

int msgsnd (int msqid, const void *ptr, size_t length, int flag);

/* возвращает 0 в случае успешного завершения, -1 – в случае ошибки */

Здесь msqid представляет собой идентификатор очереди, возвращаемый msgget. Указатель ptr ссылается на структуру, определенную в файле <sys/msg.h> и содержащую следующие поля:

struct msgbuf

{

long mtype; /* тип сообщения, должен быть > 0 */

char mtext[1]; /* данные */

};

Тип сообщения должен быть больше нуля, поскольку неположительные типы используются специальным образом функцией msgrcv, о чем рассказывается в следующем разделе.

Название mtext в структуре msgbuf употреблено не вполне правильно; данные в сообщении вовсе не обязаны быть текстовыми. Разрешена передача любых типов данных как в двоичном, так и в текстовом формате. Ядро никак не интерпретирует содержимое сообщения. Можно использовать сообщения нулевой длины, то есть без поля mtext.

Большинство приложений не пользуются этим определением структуры msgbuf, поскольку выделенного в поле mtext количества данных (1 байт) обычно недостаточно для прикладных задач. На количество данных в сообщении никаких ограничений при компиляции не накладывается (как правило, оно может быть изменено системным администратором), поэтому вместо объявления структуры с большим объемом данных (большим, чем поддерживается текущей реализацией) определяется этот шаблон. Большинство приложений затем определяют собственную структуру сообщений, в которой передаваемые данные зависят от нужд этих приложений.

Например, если приложению нужно передавать сообщения, состоящие из 16-разрядного целого, за которым следует 8-байтовый массив символов, оно может определить свою собственную структуру так:

#define MY_DATA 8

typedef struct my_msgbuf

{

long mtype; /* тип сообщения */

int16_t mshort; /* начало данных */

char mchar[MY_DATA];

} Message;

Аргумент length функции msgsnd указывает длину сообщения в байтах. Это длина пользовательских данных, следующих за типом сообщения (целое типа long). Длина может быть и 0. В указанном выше примере длина может быть вычислена как sizeof(Message)-sizeof(long).

Аргумент flag может быть либо 0, либо IPC_NOWAIT. В последнем случае он отключает блокировку для msgsnd: если для нового сообщения недостаточно места в очереди, возврат из функции происходит немедленно. Это может произойти, если:

  • в данной очереди уже имеется слишком много данных (значение msg_qbytesв структуреmsqid_ds);

  • во всей системе имеется слишком много сообщений.

Если верно одно из этих условий и установлен флаг IPC_NOWAIT, функцияmsgsndвозвращает ошибку с кодомEAGAIN. Если флагIPC_NOWAITне указан, а одно из этих условий выполняется, поток приостанавливается до тех пор, пока не произойдет одно из нижеследующего:

  • для сообщения освободится достаточно места;

  • очередь с идентификатором msqidбудет удалена из системы (в этом случае возвращается ошибка с кодомEIDRM);

  • вызвавший функцию процесс (поток) будет прерван перехватываемым сигналом (в этом случае возвращается ошибка с кодом EINTR).

Соседние файлы в папке Chapter.4