/* Создаем очередь или присоединяемся к уже существующей */

 if ((id = msgget(key, IPC_CREAT | 0660)) == -1) {

  printf('Ошибка при создании очереди ');

  exit(1);

 }

 /* Заполняем сообщение */

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

                  должен быть положительным! */

 msg.op_.type = 0; /* тип операции */

 msg.l_op = 6;

 msg.r_op = 5;

 /* определяем длину сообщения - 4 байта */

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

 if ((res = msgsnd(id, &buf, length, 0)) == -1) {

  printf('Ошибка при постановке сообщения в очередь ');

  exit(1);

 }

}

После запуска этой программы запустите программу ipcs и посмотрите на статус только что отправленного сообщения. Теперь напишем программу, которая получит это сообщение.

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('Сообщение слишком большое ');

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

 /* и т.д. */

 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. Тотальный контроль

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату