Скачиваний:
56
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

Программа etest

(* Программа etest - ввод имен объектов в очередь. *)

{$mode objfpc}

uses ipc,linux,stdio,sysutils;

{$i q.inc}

var

priority:longint;

begin

if paramcount <> 2 then

begin

writeln(stderr, 'Применение: ',paramstr(0),' имя приоритет');

halt (1);

end;

try

priority:=strtoint(paramstr(2));

except

on e:econverterror do

begin

warn ('Нечисловой приоритет');

halt (2);

end;

end;

if (priority <= 0) or (priority > MAXPRIOR) then

begin

warn ('Недопустимый приоритет');

halt (2);

end;

if not enter (paramstr(1), priority) then

begin

warn ('Ошибка в процедуре enter');

halt (3);

end;

halt (0);

end.

Программа stest

(* Программа stest - простой сервер для очереди *)

uses ipc,linux,stdio,sysutils;

{$i q.inc}

function proc_obj (msg:pq_entry):integer;

begin

writeln(#$a'Приоритет: ',msg^.mtype,' имя: ',msg^.mtext);

end;

var

pid:longint;

begin

pid := fork;

case pid of

0: (* дочерний процесс *)

serve;

-1: (* сервер не существует *)

warn ('Не удалось запустить сервер');

else

writeln('Серверный процесс с идентификатором ', pid);

end;

if pid <> -1 then

halt (0)

else

halt (1);

end.

Ниже следует пример использования этих двух простых программ. Перед запуском программы stest в очередь вводятся четыре простых сообщения при помощи программы etest. Обратите внимание на порядок, в котором выводятся сообщения:

$ etest objname1 3

$ etest objname2 4

$ etest objname3 1

$ etest objname4 9

$ stest

Серверный процесс с идентификатором 2545

$

Приоритет 1 имя objname3

Приоритет 3 имя objname1

Приоритет 4 имя objname2

Приоритет 9 имя objname4

Упражнение 8.3. Измените процедуры enter и serve так, чтобы можно было посылать серверу управляющие сообщения. Зарезервируйте для таких сообщений единичный тип сообщения (как это повлияет на расстановку приоритетов?). Реализуйте следующие возможности:

1. Остановка сервера.

2. Стирание всех сообщений из очереди.

3. Стирание сообщений с заданным уровнем приоритета.

Системный вызов msgctl

Процедура msgctl служит трем целям: она позволяет процессу получать информацию о статусе очереди сообщений, изменять некоторые из связанных с очередью ограничений или удалять очередь из системы.

Описание

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, которая изменяет связанные с очередью права доступа. Очередь сообщений также должна указываться значением ее ключа.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal