Чтение онлайн

на главную - закладки

Жанры

Linux: Полное руководство

Аллен Питер В.

Шрифт:

26.5.4. Получение сообщений очереди

Для получения сообщения используется системный вызов msgrcv:

int msgrcv(int msqid, struct msgbuf *msgp, int msgsz,

 long mtype, int msgflg);

Первый аргумент определяет очередь, из которой нужно получить сообщение. Второй аргумент — это адрес буфера, в который будет записано сообщение. Третий аргумент — это ограничитель длины сообщения. Четвертый аргумент — это тип сообщения. Ядро будет искать в очереди наиболее старое сообщение данного типа и вернет его копию. Если mtype=0, то ядро вернет самое старое сообщение независимо от типа.

После успешного получения сообщения оно удаляется из очереди.

В случае успеха вызов msqrcv возвращает число байтов, скопированных в буфер, или -1 в случае ошибки. Переменная errno устанавливается следующим образом:

♦ E2BIG — длина сообщения больше, чем ограничитель msgsz;

♦ EACCESS — у вас недостаточно прав;

♦ EFAULT — недоступен адрес буфера;

♦ EIDRM — очередь уничтожена ядром;

♦ EINTR — операция прервана поступившим сигналом;

♦ EINVAL — ошибка в аргументах, например, отрицательный размер сообщения или неверный номер очереди;

♦ ENOMSG — нет сообщения, удовлетворяющего условию. Посылается, если установлен флаг IPC_NOWAIT, в противном случае процесс будет ждать нужного сообщения.

Последний аргумент предоставляет дополнительные возможности по работе с сообщениями. Если установлен бит MSG_NOERROR в msgflg, то если размер сообщения больше, чем msgsz, оно будет обрезано и вы получите только msgsz байтов. Если флаг MSG_NOERROR не устанавливать, вы получите ошибку E2BIG.

Следующий код получает сообщение из очереди:

int id; /* ID очереди */

int res, length; /* результат операции и длина */

struct my_buf buf; /* буфер */

int type = 1; /* тип сообщения */

length = sizeof(struct my_buf) — sizeof(long);

if ((res =

 msgrcv(id, &buf, length, type, 0)) == -1) {

 printf("Ошибка!");

 /* можно проанализировать ошибку */

 if (errno==E2BIG) printf("Сообщение слишком большое\n");

 if (errno==EACCESS) printf("Heт доступа\n");

 /* и т.д. */

 exit(1);

}

26.5.5. Проверка наличия сообщения в очереди

Наверное, вы не хотите, чтобы ваша программа ждала, пока в очереди появится нужное сообщение. Используя особенности системного вызова msgrcv, можно написать код проверки наличия сообщения определенного типа в очереди. Напишем функцию msg_exists, которая будет возвращать TRUE, если сообщение есть в очереди, или FALSE, если сообщения в очереди нет.

int msg_exists(int id, long type) {

 int res;

 if ((result = msgrcv(id, NULL, 0, type, IPC_NOWAIT)) == -1) {

if (errno == E2BIG)

return(TRUE);

 }

 return(FALSE);

}

В вызове msgrcv отсутствует адрес буфера и длина сообщения. Этим мы специально провоцируем ошибку, а вызов IPC_NOWAIT отказывает от блокировки процесса. Мы проверяем errno; если он равен E2BIG, значит, сообщение есть в очереди. Ошибка E2BIG порождается потому, что мы установили размер сообщения равным 0.

26.5.6. Тотальный контроль

До сих пор мы рассматривали только системные вызовы для работы с сообщениями очереди, сейчас рассмотрим системный вызов msgctl, предназначенный для контроля самой очереди.

int msgctl(int msgqid, int cmd, struct msqid_ds *buf);

Первый аргумент — это 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".

int change_mode(int id, char *mode) {

 struct msqid_ds buf;

 /* Получаем копию структуры в буфер buf */

 if (msgctl(id, IPC_STAT, &buf) == -1) {

return(-1);

 }

 /* Изменяем права доступа */

 sscanf(mode, "%ho", &buf.msg_perm.mode);

 /* Модернизируем внутреннюю структуру */

Поделиться:
Популярные книги

Газлайтер. Том 6

Володин Григорий
6. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 6

Камень Книга двенадцатая

Минин Станислав
12. Камень
Фантастика:
боевая фантастика
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Камень Книга двенадцатая

Аристократ из прошлого тысячелетия

Еслер Андрей
3. Соприкосновение миров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Аристократ из прошлого тысячелетия

#НенавистьЛюбовь

Джейн Анна
Любовные романы:
современные любовные романы
6.33
рейтинг книги
#НенавистьЛюбовь

Локки 8. Потомок бога

Решетов Евгений Валерьевич
8. Локки
Фантастика:
фэнтези
боевая фантастика
героическая фантастика
попаданцы
5.00
рейтинг книги
Локки 8. Потомок бога

Тринадцатый V

NikL
5. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый V

Законы Рода. Том 6

Андрей Мельник
6. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 6

По прозвищу Святой. Книга вторая

Евтушенко Алексей Анатольевич
2. Святой
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
По прозвищу Святой. Книга вторая

Неудержимый. Книга XXVI

Боярский Андрей
26. Неудержимый
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXVI

Я – Легенда

Гарцевич Евгений Александрович
1. Я - Легенда!
Фантастика:
боевая фантастика
попаданцы
рпг
фантастика: прочее
5.00
рейтинг книги
Я – Легенда

Последний Герой. Том 3

Дамиров Рафаэль
3. Последний герой
Фантастика:
попаданцы
альтернативная история
фантастика: прочее
5.00
рейтинг книги
Последний Герой. Том 3

Император Пограничья 8

Астахов Евгений Евгеньевич
8. Император Пограничья
Фантастика:
городское фэнтези
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 8

Законы рода

Андрей Мельник
1. Граф Берестьев
Фантастика:
фэнтези
боевая фантастика
аниме
5.00
рейтинг книги
Законы рода

Идеальный мир для Лекаря 14

Сапфир Олег
14. Лекарь
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 14