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

5.7. Синхронизация процессов

5.7.1. Системный вызов wait Описание

uses stdio;

function wait(status:pinteger):longint;

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

Вызов wait часто осуществляется родительским процессом после вызова fork, например:

.

.

.

var

status:integer;

cpid:longint;

cpid := fork; (*Создать новый процесс *)

if cpid = 0 then

begin

(* Дочерний процесс *)

(* Выполнить какие-либо действия ... *)

end

else

begin

/* Родительский процесс, ожидание завершения дочернего */

cpid := wait(@status);

writeln('Дочерний процесс ', cpid, ' завершился');

end;

.

.

.

Сочетание вызовов fork и wait наиболее полезно, если дочерний процесс предназначен для выполнения совершенно другой программы при помощи вызова ехеc.

Возвращаемое значение wait обычно является идентификатором дочернего процесса, который завершил свою работу. Если вызов wait возвращает значение -1, это может означать, что дочерние процессы не существуют, и в этом случае переменная linuxerror будет содержать код ошибки Sys_ECHILD. Возможность определить завершение каждого из дочерних процессов по отдельности означает, что родительский процесс может выполнять цикл, ожидая завершения каждого из потомков, а после того, как все они завершатся, продолжать свою работу.

Вызов wait принимает один аргумент, status, – указатель на целое число. Если указатель равен nil, то аргумент просто игнорируется. Если же вызову wait передается допустимый указатель, то после возврата из вызова wait переменная status будет содержать полезную информацию о статусе завершения процесса. Обычно эта информация будет представлять собой код завершения дочернего процесса, переданный при помощи вызова halt.

Следующая программа status показывает, как может быть использован вызов wait:

(* Программа status -- получение статуса завершения потомка *)

uses linux,stdio;

var

pid:longint;

status, exit_status:integer;

begin

pid := fork;

if pid < 0 then

fatal ('Ошибка вызова fork ');

if pid = 0 then (* потомок *)

begin

(* Вызвать библиотечную процедуру sleep

* для временного прекращения работы на 4 секунды

*)

sleep(4);

halt(5); (* выход с ненулевым значением *)

end;

(* Если мы оказались здесь, то это родительский процесс, *)

(* поэтому ожидать завершения дочернего процесса *)

pid := wait(@status);

if pid = -1 then

begin

perror ('Ошибка вызова wait ');

halt(2);

end;

(* Проверка статуса завершения дочернего процесса *)

if WIFEXITED (status) then

begin

exit_status := WEXITSTATUS (status);

writeln ('Статус завершения ',pid,' равен ', exit_status);

end;

halt(0);

end.

Значение, возвращаемое родительскому процессу при помощи вызова halt, записывается в старшие восемь бит целочисленной переменной status. Чтобы оно имело смысл, младшие восемь бит должны быть равны нулю. Функция WIFEXITED (определенная в модуле stdio) проверяет, так ли это на самом деле. Если WIFEXITED возвращает false, то это означает, что выполнение дочернего процесса было остановлено (или прекращено) другим процессом при помощи межпроцессного взаимодействия, называемого сигналом (signal) и рассматриваемого в главе 6.

Упражнение 5.8. Переделайте процедуру docommand так, чтобы она возвращала статус вызова halt выполняемой команды. Что должно происходить, если вызов wait возвращает значение -1?

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