131
Рисунок 3.6 — Пример работы двух дополнительных нитей процесса
Формально, стандарт POSIX-2001 под сигналом понимает «механизм», с помощью которого процесс или поток управления уведомляют о некотором событии, произошедшем в системе, или подвергают воздействию этого события.
Примерами подобных событий могут служить аппаратные исключительные ситуации и специфические действия процессов.
Термин "сигнал" используется также для обозначения самого события.
Говорят, что сигнал генерируется (или посылается) для процесса (потока управления), когда происходит вызвавшее его событие:
• выявлен аппаратный сбой;
132
•отработал таймер;
•пользователь ввел с терминала специфическую последовательность символов;
•процесс обратился к функции kill(...) и другие.
Иногда, по одному событию генерируются сигналы для нескольких процессов, например, для группы процессов, ассоциированных с некоторым управляющим терминалом.
В момент генерации сигнала определяется, посылается ли он процессу или конкретному потоку управления в процессе. Сигналы, сгенерированные в результате действий, приписываемых отдельному потоку управления, таких как возникновение аппаратной исключительной ситуации, посылаются этому потоку.
Сигналы, генерация которых ассоциирована с идентификатором процесса или группы процессов, а также с асинхронным событием, например, пользовательский ввод с терминала, посылаются процессу. В каждом процессе определены действия, предпринимаемые в ответ на все предусмотренные системой сигналы.
Говорят, что сигнал доставлен процессу, когда взято для выполнения действие, соответствующее данным процессу и сигналу.
В интервале, от генерации до доставки или принятия сигнал называется ждущим. Обычно, он невидим для приложений, однако доставку сигнала потоку управления можно блокировать. Если действие, ассоциированное с заблокированным сигналом, отлично от игнорирования, он будет ждать разблокирования.
У каждого потока управления есть маска сигналов, определяющая набор блокируемых сигналов. Обычно она достается в наследство от родительского потока.
В данном подразделе, мы завершаем рассмотрение базовых системных вызовов управления процессами, объединенными в группу «Функции потоков и сигна-лов процессов», где будут изучены следующие системные вызовы:
•signal() - установка нового обработчика сигнала текущего процесса;
•kill() - посылка сигнала процессу по его иденитфикатору PID;
•raise() - посылка сигнала текущему процессу;
•pause() - остановка процесса до получения сигнала;
•sleep() - остановка процесса на заданное число секунд, либо до получения сигнала.
Установка реакции процесса на получаемые сигналы осуществляется с помошью системного вызова:
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
где signum — номер обрабатываемого сисгнала;
handler — ассоциируется с действем одного из трех типов:
• SIG_DFL — выполняются подразумеваемые действия, зависящие от сигнала,
133
которые описаны в заголовочном файле <signal.h>;
•SIG_IGN - игнорировать сигнал; доставка сигнала не оказывает воздействия на процесс;
•указатель на функцию - обработать сигнал, выполнив при его доставке заданную функцию; после завершения функции обработки процесс возобновляет
выполнение с точки прерывания.
Обычно, функция обработки вызывается в соответствии со следующим заголовком языка C:
void func (int signo);
где signo - номер доставленного сигнала.
Замечание
Первоначально, до входа в функцию main(...), реакция на все сигналы установлена как
SIG_DFL или SIG_IGN.
Функция обработки называется асинхронно-сигнально-безопасной (АСБ), если ее можно вызывать без каких-либо ограничений при обработке сигналов.
Встандарте POSIX-2001, имеется список функций, которые должны быть либо повторно входимыми, либо непрерываемыми сигналами, что превращает их в АСБ-функции.
Вэтот список включены 117 функций.
Процессу - сигнал может быть послан либо из командной строки с помощью служебной программы kill, либо из процесса с помощью системных вызовов:
#include <signal.h>
int kill (pid_t pid, int sig); int raise(int sig);
где pid — может принимать следующие значения:
•pid > 0 - сигнал sig посылается процессу с идентификатором pid;
•pid = 0 - sig посылается каждому процессу, который входит в группу текущего процесса;
•pid = -1 - sig посылается каждому процессу, за исключением процесса с номером 1;
•pid < -1 - sig посылается каждому процессу, который входит в группу
процесса с идентификатором -pid. sig — номер обрабатываемого сигнала.
Замечание
Если sig=0, то действия сводятся к проверке допустимости значения pid.
134
В случае успеха, возвращается ноль. При ошибке, возвращается -1 и значение errno устанавливается:
•EINVAL -задан неправильный сигнал;
•ESRCH - идентификатор процесса pid или группа процесса не существуют. Заметим, что существующий процесс может быть зомби - процессом, который уже находится в состоянии завершения, но пока в котором пока ещё не выполнился wait(...).
•EPERM - текущий процесс не имеет прав на посылку сигнала к любому из указанных процессов; процессы, которые имеют права на посылку сигнала процессу с номером pid должны иметь привелегии суперпользователя или, реальный или эффективный идентификатор пользователя процесса, посылающего сигнал, должен быть таким же как реальный или эффективный идентификатор пользователя процесса, принимающего сигнал; в случае, когда посылающий и принимающий процессы относятся к одной сессии, становится доступным сигнал SIGCONT.
Замечание
Процесс имеет право послать сигнал адресату, заданному аргументом pid, если он (процесс) имеет соответствующие привилегии или его реальный или действующий идентификатор пользователя совпадает с реальным или сохраненным идентификатором адресата.
Вызов служебной программы kill в виде: kill -l, позволяет вывести на терминал весь список сигналов, поддерживаемых используемой ОС:
1) SIGHUP |
2) |
SIGINT |
3) |
SIGQUIT |
4) |
SIGILL |
|
5) SIGTRAP |
6) |
SIGABRT |
7) |
SIGBUS |
8) |
SIGFPE |
|
9) SIGKILL |
10) |
SIGUSR1 |
11) |
SIGSEGV |
12) |
SIGUSR2 |
|
13) |
SIGPIPE |
14) |
SIGALRM |
15) |
SIGTERM |
17) |
SIGCHLD |
18) |
SIGCONT |
19) |
SIGSTOP |
20) |
SIGTSTP |
21) |
SIGTTIN |
22) |
SIGTTOU |
23) |
SIGURG |
24) |
SIGXCPU |
25) |
SIGXFSZ |
26) |
SIGVTALRM |
27) |
SIGPROF |
28) |
SIGWINCH |
29) |
SIGIO |
30) |
SIGPWR |
31) |
SIGSYS |
32) |
SIGRTMIN |
33) |
SIGRTMIN+1 |
34) |
SIGRTMIN+2 |
35) |
SIGRTMIN+3 |
36) |
SIGRTMIN+4 |
37) |
SIGRTMIN+5 |
38) |
SIGRTMIN+6 |
39) |
SIGRTMIN+7 |
40) |
SIGRTMIN+8 |
41) |
SIGRTMIN+9 |
42) |
SIGRTMIN+10 |
43) |
SIGRTMIN+11 |
44) |
SIGRTMIN+12 |
45) |
SIGRTMIN+13 |
46) |
SIGRTMIN+14 |
47) |
SIGRTMIN+15 |
48) |
SIGRTMAX-15 |
49) |
SIGRTMAX-14 |
50) |
SIGRTMAX-13 |
51) |
SIGRTMAX-12 |
52) |
SIGRTMAX-11 |
53) |
SIGRTMAX-10 |
54) |
SIGRTMAX-9 |
55) |
SIGRTMAX-8 |
56) |
SIGRTMAX-7 |
57) |
SIGRTMAX-6 |
58) |
SIGRTMAX-5 |
59) |
SIGRTMAX-4 |
60) |
SIGRTMAX-3 |
61) |
SIGRTMAX-2 |
62) |
SIGRTMAX-1 |
63) |
SIGRTMAX |
|
|
|
|
Стандарт языка C определяет имена всего шести сигналов: SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV и SIGTERM.
ОС Linux поддерживает сигналы режима реального времени, включенные в POSIX 1003.1-2001, которые соответствуют 32 сигналам, начиная с номера 32 (SIGRTMIN) до номера 63 (SIGRTMAX).
В отличие от стандартных сигналов, сигналы режима реального времени не имеют предопределенных заранее значений: весь набор сигналов режима реального времени приложения могут использовать так, как им будет нужно.
135
Замечание
Программы должны всегда ссылаться на сигналы режима реального времени, используя записи SIGRTMIN+n, так как диапазон номеров таких сигналов варьируется в системах Unices.
Стандарт POSIX-2001 определяет как обязательные для реализации сигналы, представленные в таблице 3.3.
Таблица 3.3 - Сигналы, определенные стандартом POSIX
Сигнал |
Описание сигнала |
SIGABRT |
Сигнал аварийного завершения процесса. Подразумеваемая |
|
реакция предусматривает, помимо аварийного завершения, |
|
создание файла с образом памяти процесса. |
SIGALRM |
Срабатывание будильника. Подразумеваемая реакция — аварий- |
|
ное завершение процесса. |
SIGBUS |
Ошибка системной шины как следствие обращения к неоп- |
|
ределенной области памяти. Подразумеваемая реакция — ава- |
|
рийное завершение и создание файла с образом памяти процесса. |
SIGCHLD |
Завершение, остановка или продолжение порожденного процес- |
|
са. Подразумеваемая реакция - игнорирование. |
SIGCONT |
Продолжение процесса, если он был остановлен. |
|
Подразумеваемая реакция - продолжение выполнения или игно- |
|
рирование, если процесс не был остановлен. |
SIGFPE |
Некорректная арифметическая операция. |
|
Подразумеваемая реакция - аварийное завершение и создание |
|
файла с образом памяти процесса. |
SIGHUP |
Сигнал разъединения. |
|
Подразумеваемая реакция - аварийное завершение процесса. |
SIGILL |
Некорректная команда. Подразумеваемая реакция - аварийное |
|
завершение и создание файла с образом памяти процесса. |
SIGINT |
Сигнал прерывания, поступивший с терминала. |
|
Подразумеваемая реакция - аварийное завершение процесса. |
SIGKILL |
Уничтожение процесса (этот сигнал нельзя перехватить для об- |
|
работки или проигнорировать). |
|
Подразумеваемая реакция - аварийное завершение процесса. |
SIGPIPE |
Попытка записи в канал, из которого никто не читает. |
|
Подразумеваемая реакция - аварийное завершение процесса. |
SIGQUIT |
Сигнал выхода, поступивший с терминала. |
|
Подразумеваемая реакция - аварийное завершение и создание |
|
файла с образом памяти процесса. |
SIGSEGV |
Некорректное обращение к памяти. |