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

Пример работы с семафорами

Теперь продолжим пример, который начали с процедуры initsem. Он содержит две процедуры р() и v(), реализующие традиционные операции над семафорами. Сначала рассмотрим р():

{$i pv.inc}

(* Процедура p.pas - операция p для семафора *)

function p (semid:longint):longint;

var

p_buf:tsembuf;

begin

p_buf.sem_num := 0;

p_buf.sem_op := -1;

p_buf.sem_flg := SEM_UNDO;

if not semop (semid, @p_buf, 1) then

begin

perror ('ошибка операции p(semid)');

halt (1);

end;

p:=0;

end;

Обратите внимание на то, что здесь использован флаг SEM_UNDO. Теперь рассмотрим текст процедуры v().

{$i pv.inc}

(* Процедура v.pas - операция v для семафора *)

function v (semid:longint):longint;

var

v_buf:tsembuf;

begin

v_buf.sem_num := 0;

v_buf.sem_op := 1;

v_buf.sem_flg := SEM_UNDO;

if not semop (semid, @v_buf, 1) then

begin

perror ('Ошибка операции v(semid)');

halt (1);

end;

v:=0;

end;

Можно продемонстрировать использование этих довольно простых процедур для реализации взаимного исключения. Рассмотрим следующую программу:

(* Программа testsem - проверка процедур работы с семафорами *)

uses ipc,stdio,linux;

{$i pv.inc}

procedure handlesem (skey:tkey);

var

semid, pid:longint;

begin

pid := getpid;

semid := initsem (skey);

if semid < 0 then

halt (1);

writeln (#$a'Процесс ',pid,' перед критическим участком');

p (semid);

writeln ('Процесс ',pid,' выполняет критический участок');

(* В реальной программе здесь выполняется нечто осмысленное *)

sleep (10);

writeln ('Процесс ',pid,' покинул критический участок');

v (semid);

writeln ('Процесс ',pid,' завершает работу');

halt (0);

end;

const

semkey:tkey = $200;

var

i:integer;

begin

for i := 1 to 3 do

if fork = 0 then

handlesem (semkey);

end.

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

Процесс 799 перед критическим участком

Процесс 799 выполняет критический участок

Процесс 800 перед критическим участком

Процесс 801 перед критическим участком

Процесс 799 покинул критический участок

Процесс 801 выполняет критический участок

Процесс 799 завершает работу

Процесс 801 покинул критический участок

Процесс 801 завершает работу

Процесс 800 выполняет критический участок

Процесс 800 покинул критический участок

Процесс 800 завершает работу

8.3.4. Разделяемая память

Операции с разделяемой памятью позволяют двум и более процессам совместно использовать область физической памяти (общеизвестно, что обычно области данных любых двух программ совершенно отделены друг от друга). Чаще всего разделяемая память является наиболее производительным механизмом межпроцессного взаимодействия.

Для того, чтобы сегмент памяти мог использоваться совместно, он должен быть сначала создан при помощи системного вызова shmget. После создания сегмента разделяемой памяти процесс может подключаться к нему при помощи вызова shmat и затем использовать его для своих частных целей. Когда этот сегмент памяти больше не нужен, процесс может отключиться от него при помощи вызова shmdt.

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