Первый из вызовов, msgsnd, используется
uses ipc;
Function msgsnd(mqid:longint; message:PMSGBuf; size:longint;
msg_type:longint; flags:longint): Boolean;
Function msgrcv(mqid:longint; message:PMSGBuf; size:longint;
msg_type:longint; flags:longint): Boolean;
Первый из вызовов, msgsnd, используется для добавления сообщения в очередь, обозначенную идентификатором mqid.
Сообщение содержится в структуре message – шаблоне, определенном пользователем и имеющем следующую форму:
PMSGbuf=^TMSGbuf;
TMSGbuf=record
mtype:longint; (* Тип сообщения *)
mtext:array [0..SOMEVALUE-1] of char; (* Текст сообщения *)
end;
Значение поля mtype может использоваться программистом для разбиения сообщений на категории. При этом значимыми являются только положительные значения; отрицательные или нулевые не могут использоваться (это будет видно из дальнейшего описания операций передачи сообщений). Массив mtext служит для хранения данных сообщения (постоянная SOMEVALUE выбрана совершенно произвольно). Длина посылаемого сообщения задается параметром size вызова msgsnd и может быть в диапазоне от нуля до меньшего из двух значений SOMEVALUE и максимального размера сообщения, определенного в системе.
Параметр flsgs вызова msgsnd может нести только один флаг: IPC_NOWAIT. При неустановленном параметре IPC_NOWAIT вызывающий процесс приостановит работу, если для посылки сообщения недостаточно системных ресурсов. На практике это произойдет, если полная длина сообщений в очереди превысит максимум, заданный для очереди или всей системы. Если флаг IPC_NOWAIT установлен, тогда при невозможности послать сообщение возврат из вызова произойдет немедленно. Возвращаемое значение будет равно -1, и переменная ipcerror будет иметь значение Sys_EAGAIN, означающее необходимость повторения попытки.
Вызов msgsnd также может завершиться неудачей из-за установленных прав доступа. Например, если ни действующий идентификатор пользователя, ни действующий идентификатор группы процесса не связаны с очередью, и установлен код доступа к очереди octal(0660), то вызов msgsnd для этой очереди завершится неудачей. Переменная ipcerror получит значение Sys_EACCES.
Перейдем теперь к чтению сообщений. Для чтения из очереди, заданной идентификатором mqid, используется вызов msgrcv. Чтение разрешено, если процесс имеет права доступа к очереди на чтение. Успешное чтение сообщения приводит к удалению его из очереди.
На этот раз переменная message используется для хранения полученного сообщения, а параметр size задает максимальную длину сообщений, которые могут находиться в этой структуре. Успешный вызов возвращает длину полученного сообщения.
Параметр msg_type определяет тип принимаемого сообщения, он помогает выбрать нужное из находящихся в очереди сообщений. Если параметр msg_type равен нулю, из очереди считывается первое сообщение, то есть то, которое было послано первым. При ненулевом положительном значении параметра msg_type считывается первое сообщение из очереди с заданным типом сообщения. Например, если очередь содержит сообщения со значениями mtype 999, 5 и 1, а параметр msg_type в вызове msgrcv имеет значение 5, то считывается сообщение типа 5. И, наконец, если параметр msg_type имеет ненулевое отрицательное значение, то считывается первое сообщение с наименьшим значением mtype, которое меньше или равно модулю параметра msg_type. Этот алгоритм кажется сложным, но выражает простое правило: если вернуться к нашему предыдущему примеру с тремя сообщениями со значениями mtype 999, 5 и 1, то при значении параметра msg_type в вызове msgrcv равном -999 и троекратном вызове сообщения будут получены в порядке 1, 5, 999.
Последний параметр flags содержит управляющую информацию. В этом параметре могут быть независимо установлены два флага – IPS_NOWAIT и MSG_NOERROR. Флаг IPC_NOWAIT имеет обычный смысл – если он не задан, то процесс будет приостановлен при отсутствии в очереди подходящих сообщений, и возврат из вызова произойдет после поступления сообщения соответствующего типа. Если же этот флаг установлен, то возврат из вызова при любых обстоятельствах произойдет немедленно.
При установленном флаге MSG_NOERROR сообщение будет усечено, если его длина больше, чем size байт, без этого флага попытка чтения длинного сообщения приводит к неудаче вызова msgrcv. К сожалению, узнать о том, что усечение имело место, невозможно.
Этот раздел может показаться сложным: формулировка средств межпроцессного взаимодействия несколько не соответствует по своей сложности и стилю природе ОС UNIX. В действительности же процедуры передачи сообщений просты в применении и имеют множество потенциальных применений, что попробуем продемонстрировать на следующем примере.