Вход/Регистрация
Основы программирования в Linux
вернуться

Мэтью Нейл

Шрифт:

Функция

kill
завершится аварийно, вернет -1 и установит значение переменной
errno
, если задан неверный сигнал, (
errno
равна
EINVAL
), у процесса нет полномочий (
EPERM
) или заданный процесс не существует (
ESRCH
).

Сигналы предоставляют полезное средство, именуемое будильником или сигналом тревоги. Вызов функции

alarm
может применяться для формирования сигнала
SIGALRM
в определенное время в будущем.

#include <unistd.h>

unsigned int alarm(unsigned int seconds);

Вызов

alarm
намечает доставку сигнала
SIGALRM
через
seconds
секунд. В действительности сигнал будильника будет доставлен чуть позже из-за обработки задержек и учета неопределенностей. Значение 0 отменяет любой невыполненный запрос на сигнал будильника. Вызов функции
alarm
до получения сигнала может вызвать сброс графика доставки. У каждого процесса может быть только один невыполненный сигнал будильника. Функция
alarm
возвращает количество секунд, оставшихся до отправки любого невыполненного вызова,
alarm
, или -1 в случае аварийного завершения.

Для того чтобы увидеть как работает функция

alarm
, можно сымитировать ее действие, используя вызовы
fork
,
sleep
и
signal
(упражнение 11.8). Программа сможет запустить новый процесс с единственной целью — отправить сигнал спустя какое- то время.

Упражнение 11.8 Будильник

В программе alarm.c первая функция,

ding
, имитирует будильник.

#include <sys/types.h>

#include <signal.h>

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

static int alarm_fired = 0;

void ding(int sig) {

 alarm_fired = 1;

}

В функции

main
вы заставляете дочерний процесс ждать пять секунд перед отправкой сигнала
SIGALRM
в свой родительский процесс:

int main {

 pid_t pid;

 printf("alarm application starting\n");

 pid = fork;

 switch(pid) {

 case -1:

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

perror("fork failed");

exit(1);

 case 0:

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

sleep(5);

kill(getppid, SIGALRM);

exit(0);

 }

Родительский процесс устроен так, что перехватывает сигнал

SIGALRM
с помощью вызова
signal
и затем ждет неизбежности:

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

 printf("waiting for alarm to go off\n");

 (void)signal(SIGALRM, ding);

 pause;

 if (alarm_fired) printf("Ding!\n");

 printf("done\n");

 exit(0);

}

Когда вы выполните программу, то увидите, что она делает паузу на пять секунд, в течение которых ждет имитации будильника:

$ ./alarm

alarm application starting

waiting for alarm to go off

<5 second pause>

Ding!

done $

В этой программе вводится новая функция

pause
, которая просто приостанавливает выполнение программы до появления сигнала. Когда она получит сигнал, выполняется любой установленный обработчик, и выполнение продолжается как обычно. Она объявляется следующим образом:

#include <unistd.h>

int pause(void);

Функция возвращает -1 (если следующий полученный сигнал не вызвал завершения программы) с переменной

errno
, равной
EINTR
, в случае прерывания сигналом. Лучше для ожидания сигналов применять функцию
sigsuspend
, которую мы обсудим чуть позже в этой главе.

Как это работает

Программа имитации будильника запускает новый процесс вызовом

fork
. Этот дочерний процесс ожидает пять секунд и затем посылает сигнал
SIGALRM
своему родителю. Родитель подготавливается к получению сигнала
SIGALRM
и затем делает паузу до тех пор, пока не будет получен сигнал. Функция
printf
не вызывается непосредственно в обработчике, вместо этого вы устанавливаете флаг, который проверяете позже.

  • Читать дальше
  • 1
  • ...
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: