Задержка исполнения на заданный промежуток времени



Библиотечная функция sleep(3C) используется, если вы хотите задержать исполнение вашей программы на несколько секунд. Упрощенная реализация этой функции для однопоточной среды была только что обсуждена.

Перехваченный сигнал вызывает преждевременное завершение sleep(3C). Возвращаемое значение — количество "недоспанных" секунд.

 

Управление сигналами

В ОС UNIX System V Версия 3 были введены новые системные вызовы для управления сигналами, которые лучше поддерживают сигналы и исправляют некоторые из недостатков системного вызова signal(2). В частности, при перехвате сигнала, реакция на который установлена с помощью signal(2), ядро сбрасывает реакцию на него в реакцию по умолчанию. Прежде чем реакция на сигнал будет установлена в требуемое значение, вновь возникший сигнал того же типа может убить процесс.

При перехвате сигналов с использованием sigset(2) эта проблема не возникает. При получении сигнала ядро автоматически устанавливает задержку таких сигналов до возврата из функции обработки. После этого, реакция устанавливается ядром на то значение, которое было изначально задано вызовом sigset(2). Если в промежутке был задержан сигнал, он освобождается, и функция обработки вызывается снова тем же образом.

Руководство по signal(2) содержит набор вызовов, связанных с сигналами, которые обсуждались выше. Некоторые из них предоставлены далее.

sigset(2)

Системный вызов sigset(2) имеет такие же параметры, как signal(2). Реакции, которые могут быть заданы для сигнала при помощи этой функции, таковы:

 SIG_DFL - Установить реакцию на сигнал в реакцию по умолчанию. Как правило, эта реакция состоит в завершении программы.

 SIG_IGN - Игнорировать сигнал.

 SIG_HOLD - Задерживать сигналы при их прибытии. Ранее ожидавшие сигналы остаются задержанными.

func - При возникновении сигнала вызывается функция, на которую указывает func. Когда sigset вызывается с таким аргументом, задержанные сигналы освобождаются.

При установке обработчика через sigset(2), сигнал блокируется до возврата из обработчика. Но при вызове longjmp(3C) из обработчика, возврата из обработчика не происходит, и сигнал так и останется заблокированным. Для решения этой проблемы, совместно с sigset(2) необходимо использовать функции sigsetjmp(3C)/siglongjmp(3C), которые в нашем курсе подробно не изучаются.

sighold(2) После вызова sighold(2) вновь прибывающие сигналы задерживаются. Этот вызов аналогичен вызову sigset(2) с реакцией SIG_HOLD с тем отличием, что он не меняет старую реакцию на сигнал. Этот системный вызов предоставлен для удобства.

sigrelse(2) освобождает задержанные сигналы.

sigignore(2) Этот системный вызов эквивалентен вызову sigset(2) с реакцией SIG_IGN. Этот системный вызов предоставлен для удобства.

sigpause(2) Системный вызов sigpause(2) представляет собой атомарно исполняющуюся пару вызовов sigrelse(sig) и pause(2). Слово «атомарно», в данном случае, означает, что сигнал не может быть получен в интервале между sigrelse() и pause(). Если sigrelse() приведёт к доставке сигнала sig, процесс не войдёт в pause(). Системный вызов sigpause(2) представляет более элегантное решение проблемы потерянного пробуждения, чем рассматривавшаяся выше программа с применением setjmp/longjmp.

 

Задержка и освобождение сигнала - Образец

 

Этот образец кода показывает, как задерживать сигнал во время исполнения критической секции кода. Бывают ситуации, когда прибывший сигнал может влиять на правильность исполнения программы, если возникнет в неправильном месте кода. Одно решение состоит в игнорировании сигналов в этой критической секции, но при использовании такого метода сигналы могут быть потеряны.

Более удачный метод состоит в том, чтобы задержать сигналы до момента, когда программа будет готова прореагировать на сигнал. Вызов sighold(2) должен стоять перед входом в критический участок, а вызов sigrelse(2) должен быть сделан после выхода из него.

 

Файл: sighold1.c

         ЗАДЕРЖКА И ОСВОБОЖДЕНИЕ СИГНАЛА - ОБРАЗЕЦ

 

 

 1 #include <signal.h>

 2

 3 main()

 4 {

 5    void (*istat)(int), sigcatch(int);

 6

 7 istat = sigset(SIGINT, sigcatch);

 8

 9 while(1) {

10 /*

11 * processing loop ...

12 */

13

14    sighold(SIGINT);

15 /*

16  * critical section of code ...

17  */

18 sigrelse(SIGINT);

19  }

20 sigset(SIGINT, istat);

21 }

22

23

24 void sigcatch(int sig)

25 {

26 /*

27 * signal catching routine here

28 */

29  }

 


Дата добавления: 2018-06-27; просмотров: 266; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!