Системное программирование в UNIX средствами Free Pascal

Переменная mqid должна быть допустимым


uses ipc;
Function msgctl(mqid:longint; cmd:longint; msg_stat:PMSQid_ds): Boolean;
Переменная mqid должна быть допустимым идентификатором очереди. Пропуская пока параметр cmd, обратимся к третьему параметру msg_stat, который содержит адрес структуры TMSQid_ds. Эта структура определяется в файле ipc и содержит следующие элементы:
PMSQid_ds = ^TMSQid_ds;
TMSQid_ds = record
  msg_perm   : TIPC_perm; (* Владелец/права доступа *)
  msg_first  : PMsg;    
  msg_last   : PMsg;    
  msg_stime  : Longint;   (* Время посл. вызова msgsnd *)
  msg_rtime  : Longint;   (* Время посл. вызова msgrcv *)
  msg_ctime  : Longint;   (* Время посл. изменения *)
  wwait      : Pointer;
  rwait      : pointer;


  msg_cbytes : word;     
  msg_qnum   : word;      (* Число сообщений в очереди *)
  msg_qbytes : word;      (* Макс. число байтов в очереди *)
  msg_lspid  : word;      (* Идентификатор процесса,
                             последним вызвавшего msgsnd *)
  msg_lrpid  : word;      (* Идентификатор процесса,
                             последним вызвавшего msgrcv *)
end;
Структура TIPC_perm, с которой уже встречались ранее, содержит связанную с очередью информацию о владельце и правах доступа. Переменные msg_stime, msg_rtime, msg_ctime содержат число секунд, прошедшее с 00:00 по гринвичскому времени 1 января 1970 г. (Следующий пример покажет, как можно преобразовать такие значения в удобочитаемый формат.)
Параметр cmd в вызове msgctl сообщает системе, какую операцию она должна выполнить. Существуют три возможных значения этого параметра, каждое из которых может быть применено к одному из трех средств межпроцессного взаимодействия. Они обозначаются следующими константами, определенными в файле ipc.

IPC_STAT
Сообщает системе, что нужно поместить информацию о статусе объекта в структуру msg_stat
IPC_SET
Используется для задания значений управляющих параметров очереди сообщений, содержащихся в структуре msg_stat. При этом могут быть изменены только следующие поля:
msq_stat.msg_perm.uid
msq_stat.msg_perm.gid
msq_stat.msg_perm.mode
msq_stat.msg_qbytes
Операция IPC_SET завершится успехом только в случае ее выполнения суперпользователем или текущим владельцем очереди, заданным параметром msq_stat.msg_perm.uid. Кроме того, только суперпользователь может увеличивать значение msg_qbytes – максимальное количество байтов, которое может находиться в очереди
IPC_RMID
Эта операция удаляет очередь сообщений из системы. Она также может быть выполнена только суперпользователем или владельцем очереди. Если параметр command принимает значение IPC_RMID, to параметр msg_stat задается равным nil
<


Следующий пример, программа show_msg, выводит часть информации о статусе объекта очереди сообщений. Программа должна вызываться так:
$ show_msg значение_ключа
Программа show_msg использует библиотечную процедуру ctime для преобразования значений структуры time_t в привычную запись. (Процедура ctime и другие функции для работы с временными значениями будут обсуждаться в главе 12.) Текст программы show_msg:
(* Программа showmsg - выводит данные об очереди сообщений *)
{$mode objfpc}
uses ipc,stdio,sysutils;
procedure mqstat_print(mkey:tkey; msq_id:longint; mstat:pmsqid_ds);
begin
  writeln (#$a'Ключ ', mkey, ', msg_qid ', msq_id, #$a);
  writeln(mstat^.msg_qnum, ' сообщений в очереди'#$a);
  writeln('Последнее сообщение послано процессом ', mstat^.msg_lspid, ' в ',
         ctime(mstat^.msg_stime));
  writeln('Последнее сообщение принято процессом ', mstat^.msg_lrpid, ' в ',
         ctime(mstat^.msg_rtime));
end;
var
  mkey:tkey;
  msq_id:longint;
  msq_status:tmsqid_ds;
begin
  if paramcount<>1 then
  begin
    writeln(stderr, 'Применение: showmsg значение_ключа');
    halt(1);
  end;
  (* Получаем идентификатор очереди сообщений *)
  try
    mkey:=tkey(strtoint(paramstr(1)));
  except
    on e:econverterror do
    begin
      writeln(stderr, 'Нечисловой идентификатор очереди сообщений');
      halt (2);
    end;
  end;
 
  msq_id := msgget(mkey, 0);
  if msq_id = -1 then
  begin
    perror('Ошибка вызова msgget');
    halt(2);
  end;
  (* Получаем информацию о статусе *)
  if not msgctl(msq_id, IPC_STAT, @msq_status) then
  begin
    perror('Ошибка вызова msgctl');
    halt(3);
  end;
  (* Выводим информацию о статусе *)
  mqstat_print(mkey, msq_id, @msq_status);
  halt(0);
end.
Упражнение 8.4. Измените процедуру show_msg так, чтобы она выводила информацию о владельце и правах доступа очереди сообщений.
Упражнение 8.5. Взяв за основу программу chmod, напишите программу msg_chmod, которая изменяет связанные с очередью права доступа. Очередь сообщений также должна указываться значением ее ключа.

Содержание раздела