Руководство программиста для Linux


Очереди сообщений - часть 5


Первый аргумент msgsnd - идентификатор нашей очереди, возвращенный предварительным вызовом msgget. Второй аргумент, msgp - это указатель на редекларированный и загруженный буфер сообщения. Аргумент msgsz содержит длину сообщения в байтах, не учитывая тип сообщения (long 4 байта). Аргумент msgflg может быть нулем или: IPC_NOWAIT

Если очередь переполнена, то сообщение не записывается в очередь, и управление передается вызывающему процессу. Если эта ситуация не обрабатывается вызывающим процессом, то он приостанавливается (блокируется), пока сообщение не будет прочитано.

Напишем незатейливую оберточную функцию для посылки сообщения: int send_message( int qid, struct mymsgbuf *qbuf ) { int result, length; /* Длина есть в точности размер структуры минус sizeof(mtype) */ length = sizeof(struct mymsgbuf) - sizeof(long); if((result = msgsnd( qid, qbuf, length, 0)) == -1) { return(-1); } return(result); }

Эта функция пытается послать сообщение, лежащее по указанному адресу (qbuf), в очередь сообщений, идентифицированную qid. Напишем небольшую утилиту с нашими двумя оберточными функциями: #include #include #include #include main() { int qid; key_t msgkey; struct mymsgbuf { long mtype; /* тип сообщения */ int request; /* рабочий номер запроса */ double salary; /* зарплата */ } msg; /* Генерируем IPC-ключ */ msgkey = ftok(".", 'm'); /* Открываем/создаем очередь */ if (( qid = open_queue( msgkey)) == -1) { perror("open_queue"); exit(1); } /* Заполняем сообщение произвольными тестовыми данными */ msg.type = 1; /* тип сообщения должен быть положительным! */ msg.request = 1; /* элемент данных 1 */ msg.salary = 1000.00; /* элемент данных 2 (моя годовая зарплата! - авт.) */ /* Бомбим! */ if((send_message( qid, &msg )) == -1) { perror("send_message"); exit(1); } }

После создания/открытия нашей очереди принимаемся за загрузку буфера сообщения с тестовыми данными (заметьте отсутствие текстовых данных для иллюстрации нашего положения о посылке двоичной информации). Вызов нашего send_message ловко доставит сообщение в очередь.

Теперь, когда мы имеем сообщение в очереди, попытайтесь при помощи ipcs посмотреть на статус нашей очереди. Обсудим, как забрать из очереди сообщение. Для этого используется системный вызов msgrcv(): SYSTEM CALL: msgrcv(); PROTOTYPE: int msgrcv( int msqid, struct msgbuf *msgp, int msgsz, long mtype, $$) RETURNS: число байт, скопированных в буфер сообщения -1 в случае ошибки: errno = E2BIG (длина сообщения больше, чем msgsz, $$) EACCES (нет права на чтение) EFAULT (адрес, на который указывает msgp, ошибочен) EIDRM (очередь была уничтожена в период изъятия сообщения) EINTR (прервано поступившим сигналом) EINVAL (msgqid ошибочен или msgsz меньше 0) ENOMSG (установлен IPC_NOWAIT, но в очереди нет ни одного сообщения, удовлетворяющего запросу) NOTES:




Начало  Назад  Вперед



Книжный магазин