Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект 58 страниц 2002.doc
Скачиваний:
91
Добавлен:
15.06.2014
Размер:
4.07 Mб
Скачать

Посылка сигналов.

Выполняет системный вызов kill().

int kill (pid_t pid, int sig)

Тип сигнала определяется аргументом sig, а первый аргумент определяет, кому посылается сигнал.

Т. е. Процесс должен знать идентификатор того процесса, которому он хочет послать сигнал, в том числе и самому себе, но сигнал можно послать только тогда, если системный идентификатор пользователя для процесса, посылающий сигнал, совпадает с действием или истинный идентификатором пользователя для процесса, которому посылается сигнал. Процессы супер-пользователя могут посылать сигналы любым другим процессам. Если непривилегированный пользователь пытается послать сигнал, который принадлежит другому пользователю, то системный вызов kill() завершается с ошибкой и возвращает значение -1. В переменную для хранения кода ошибки errno будет помещено значение EPERM.

Если PID = 0, то сигнал посылается всем процессам из группы процессов, к которой принадлежит процесс, посылающий сигнал, в том числе и самому себе.

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

Если PID < -1 , то сигнал посылается всем процессам, идентификатор группы которых равен абсолютному значению PID.

Пример:

kill( 531 , SIGUSR1);

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

Int raise (int sig); // посылает сигнал вызывающему процессу (т.Е. Самому себе).

Пример:

raise(SIGUSR2);

Системный вызов alarm() – устанавливает таймер процесса и при срабатывании таймера, процессу посылается сигнал.

unsigned int alarm(unsigned int secs);

Переменная – аргумент, задающий время в секундах. Этот системный вызов не останавливает процесс, а продолжает выполнение до тех пор, пока не будет получен сигнал SIGALARM. Таймер продолжает отсчёт и после вызова функции exec(), но вызов fork() выключает таймер в дочернем процессе (напр.: alarm(10)). Системный вызов alarm(0), останавливает работу таймера.

Обработка сигналов.

При получении сигнала процесс может выполнить одно из трёх действий:

  1. Выполнить действие по умолчанию (предполагает во многих случаях остановку процесса). Для некоторых сигналов, действие по умолчанию является игнорируемым.

  2. Игнорирование сигнала и продолжение выполнения процесса. Используется, когда нежелательно прерывать какой-то участок программы. (Например: принимаются данные от внешних устройств).

  3. Выполнить действие, определённое программистом (составителем программы).

Диспозиция сигнала предполагает определение типа обработчика для данного сигнала.

#include<signal.h>

void (*signal(int sig, void(*disp)(int)))(int);

static void sig_hndlr(int signo)

{

signal (SIGINT, sig_hndlr);

printf (“Получен сигнал SIGINT \n”);

}

main()

{

signal (SIGINT, sig_hndlr);

signal (SIGUSR1, SIGDFL);

signal (SIGUSR2, SIGIGN);

while(1) pause();

}

SIGDFL – действие по умолчанию.

SIGIGN – игнорировать сигнал.

Системный вызов signal() имеет ограниченные возможности управления сигналами:

  1. Он не может заблокировать сигнал.

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

Функция pause() возвращает значение -1 при получении сигнала, который не игнорируется. А значение переменной errno устанавливается в код ошибки, которая обозначает получение сигнала прерывания (EINTR).