Linux: Полное руководство
Шрифт:
26.5.4. Получение сообщений очереди
Для получения сообщения используется системный вызов msgrcv:
Первый аргумент определяет очередь, из которой нужно получить сообщение. Второй аргумент — это адрес буфера, в который будет записано сообщение. Третий аргумент — это ограничитель длины сообщения. Четвертый аргумент — это тип сообщения. Ядро будет искать в очереди наиболее старое сообщение данного типа и вернет его
После успешного получения сообщения оно удаляется из очереди.
В случае успеха вызов msqrcv возвращает число байтов, скопированных в буфер, или -1 в случае ошибки. Переменная errno устанавливается следующим образом:
♦ E2BIG — длина сообщения больше, чем ограничитель msgsz;
♦ EACCESS — у вас недостаточно прав;
♦ EFAULT — недоступен адрес буфера;
♦ EIDRM — очередь уничтожена ядром;
♦ EINTR — операция прервана поступившим сигналом;
♦ EINVAL — ошибка в аргументах, например, отрицательный размер сообщения или неверный номер очереди;
♦ ENOMSG — нет сообщения, удовлетворяющего условию. Посылается, если установлен флаг IPC_NOWAIT, в противном случае процесс будет ждать нужного сообщения.
Последний аргумент предоставляет дополнительные возможности по работе с сообщениями. Если установлен бит MSG_NOERROR в msgflg, то если размер сообщения больше, чем msgsz, оно будет обрезано и вы получите только msgsz байтов. Если флаг MSG_NOERROR не устанавливать, вы получите ошибку E2BIG.
Следующий код получает сообщение из очереди:
26.5.5. Проверка наличия сообщения в очереди
Наверное, вы не хотите, чтобы ваша программа ждала, пока в очереди появится нужное сообщение. Используя особенности системного вызова msgrcv, можно написать код проверки наличия сообщения определенного типа в очереди. Напишем функцию msg_exists, которая будет возвращать TRUE, если сообщение есть в очереди, или FALSE, если сообщения в очереди нет.
В
26.5.6. Тотальный контроль
До сих пор мы рассматривали только системные вызовы для работы с сообщениями очереди, сейчас рассмотрим системный вызов msgctl, предназначенный для контроля самой очереди.
Первый аргумент — это ID очереди, второй — команда, которую нужно выполнить:
♦ IPC_STAT — записывает в буфер buf структуру msqid_ds для очереди сообщений с идентификатором msgqid.
♦ IPC_SET — устанавливает значение ipc_perm структуры msqid. Значение берется из буфера buf.
♦ IPC_RMID — удаляет очередь.
Системный вызов возвращает 0 в случае успеха и -1, если произошла ошибка. Переменная errno устанавливается следующим образом:
♦ EACCESS — недостаточно прав.
♦ EFAULT — невозможно получить доступ к адресу буфера buf или неверный адрес.
♦ EIDRM — очередь была уничтожена прямо во время запроса.
♦ EINVAL — ошибка в аргументах, например, неправильный ID очереди или отрицательный размер сообщения.
♦ EPERM — у вас нет прав на запись в очередь.
Структура msqid_ds уже рассматривалась ранее, поэтому не вижу смысла приводить ее описание еще раз.
Если подытожить, то все, что мы можем сделать с очередью — это удалить ее и изменить права доступа или информацию о владельце (его UID и GID). Как удалить, думаю, понятно. Напишем функцию change_mode, которая будет изменять права доступа к нашей очереди. Ей нужно передать два параметра — идентификатор очереди и новый режим доступа в виде строки, например, "0660".