Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб.практикумСП.doc
Скачиваний:
39
Добавлен:
31.03.2015
Размер:
5.99 Mб
Скачать

13.5. Системный вызов alarm

При синхронизации функционирования двух или более процессов часто возникает задача прерывания выполнения процессом некоторой программы, если в течение некоторого интервала времени не произойдет, то или иное событие. Для решения этой задачи, как правило, используется системный вызов alarm, который информирует ядро ОС UNIX о необходимости послать процессу, его осуществившему, сигнал побудки SIGALARM через указанное с помощью его аргумента число секунд. Если значение аргумента системного вызова alarm равно целому числу 0, то специфицированная ранее посылка процессу сигнала побудки будет отменена. Значение, возвращаемое системным вызовом alarm, представляет собой число секунд, заданное при предыдущем осуществлении этого системного вызова. Ниже приведен формат системного вызова alarm:

alarm(secs);

unsigned secs;

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

#define TO_TIME 5

#define MX_TRYS 3 /* максимум три попытки */

#include <signal.h>

#include <errno.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/tty.h>

char buffer[TTYHOG];

extern int errno;

timeout()

{

signal(SIGALRM, timeout);

}

main()

{

int n, trys = 0;

signal(SIGALRM, timeout);

while(trys< MX_TRYS) {

alarm(TO_TIME);

/* установка тайм-аута */

n = read(0, buffer, TTYHOG);

/* ожидание ввода */

alarm(0);

/* конец тайм-аута */

/* проверка ввода */

If(n < 0 && errno = = EINTR) {

fprintf(stderr, “timed out\n”);

trys++;

continue;

}

/* аварийное завершение */

if(n < 0) {

fprintf(stderr, “read error\n”);

exit(1);

}

/* достигнут конец файла */

if(n = = 0) {

fprintf(stderr, “EOF\n”);

exit(0);

}

/* выполнение копирования */

write(1, buffer, n);

trys = 0;

}

}

13.6. Управление непредусмотренными событиями

Если разработанная программа в процессе своего выполнения не осуществляет ввода с терминала, то получение процессом, в рамках которого она выполняется, сигналов SIGINT и SIGHUP является для нее событием непредусмотренным. Использование такого программного средства, как сигналы, позволяет в рамках самого процесса проанализировать возникшее событие и в соответствии с заранее подготовленным алгоритмом обработать его. Известно, что при разработке пользовательских программ часто приходится прибегать к следующему приему: разрабатываемая программа в процессе своего функционирования создает один или более так называемых временных файлов, которые после завершения выполнения такой программы удаляются из файловой системы ОС Unix. Понятно, что при аварийном завершении выполнения такой программы указанные временные файлы могут остаться неудаленными. Причиной аварийного завершения программы может стать, например, получение сигнала SIGINT процессом, в рамках которого она выполняется. Посылка же процессу указанного сигнала может быть вызвана вводом с терминала специального символа INTERRUPT. Итак, приведем исходный текст программы на языке Си, в которой описанная выше проблема решается с помощью системного вызова signal:

#include <signal.h>

main()

{

int cleanup();

if(signal(SIGINT, SIG_IGN) != SIG_IGN)

signal(SIGINT, cleanup);

……………….

creat(tempfile, 0);

……………….

unlink(tempfile);

exit(0);

}

/* Выход по получении прерывания от терминала */

сleanup()

{

unlink(tempfile);

fprintf(stderr, “Terminated Abnormally\n”);

exit(1);

}

В результате ввода с терминала специального символа INTERRUPT всем процессам, ассоциированным с данным пользовательским терминалом, будет послан сигнал SIGINT. Однако получение процессом, в рамках которого выполняется эта программа, сигнала SIGINT приведет к тому, что последний сначала вызовет на выполнение функцию сleanup, которая осуществит удаление созданных временных файлов, а затем выведет на терминал соответствующее информационное сообщение и завершит свое функционирование. Добавим, что когда пользователь вызывает программу на выполнение в асинхронном режиме, интерпретатор команд shell выполняет ряд аналогичных действий, проиллюстрировать которые можно с помощью фрагмента программы на языке Си:

if(fork() = = 0) {

signal(SIGHUP, SIG_IGN);

signal(SIGINT, SIG_IGN);

exec(cmd);

}