Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

void handler(int signum, siginfo_t *siginfo, void *context);

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

SA_SIGINFO
члена
sa_mask
структуры
struct sigaction
, применяемой для регистрации обработчика сигнала. Член
sa_handler
также не используется, потому что он является указателем на функцию с другим прототипом. Вместо этого новый член,
sa_sigaction
, указывает на обработчик сигнала с правильным прототипом. Чтобы снизить потребление памяти,
sa_handler
и
sa_sigaction
разрешено использовать один и тот же участок памяти, поэтому только один из двух должен применяться в одно и то же время. Чтобы сделать это прозрачным, библиотека С определяет
struct sigaction
следующим образом.

#include <signal.h>

struct sigaction {

 union {

__sighandler_t sa_handler;

__sigaction_t sa_sigaction;

 } __sigaction_handler;

 sigset_t sa_mask;

 unsigned long sa_flags;

};

#define sa_handler __sigaction_handler.sa_handler

#define sa_sigaction __sigaction_handler.sa_sigaction

Использование

представленной комбинации объединений и макросов позволяет этим двум членам разделять одну и ту же память без необходимости усложнения с точки зрения приложений.

Структура

siginfo_t
содержит информацию о том, где и почему был сгенерирован сигнал. Всем сигналам доступны два члена:
sa_signo
и
si_code
. Какие другие члены доступны — зависит от конкретного сигнала, и эти члены разделяют память подобно тому, как это делают члены
sa_handler
и
sa_sigaction
структуры
struct sigaction
. Член
sa_signo
содержит номер доставленного сигнала и всегда равен значению первого параметра, переданного обработчику сигнала, в то время как
si_code
указывает, почему сигнал был сгенерирован, и изменяется в зависимости от номера сигнала. Для большинства сигналов он может принимать перечисленные ниже значения. [70]

70

Существует гораздо больше значений

si_code
, нежели мы обсуждаем здесь, и эти значения имеют отношение к асинхронному вводу-выводу, очередям сообщений и таймерам реального времени, что выходит за границы тем, обсуждаемых в книге.

SI_USER

Приложение пространства пользователя вызвало

kill
для отправки сигнала. Примечание. Функция
sigsend
, включенная в Linux для совместимости с некоторыми системами Unix, также выдает
SI_USER
.

SI_QUEUE

Приложение пространства пользователя вызвало

sigqueue
для от правки сигнала, что обсуждается в самом конце этой главы.

SI_TKILL

Приложение пространства пользователя вызвало

tkill
. В то время как ядро Linux использует
SI_TKILL
, его значение не специфицировано в текущей версии библиотеки С.

Если вам нужно проверить

SI_TKILL
, используйте следующий сегмент кода для определения этого значения:

#ifndef SI_TKILL

#define SI_TKILL -6

#endif

SI_TKILL
не специфицирован ни в каком стандарте (хотя допускается ими), поэтому его следует применять осторожно в переносимых программах.

SI_KERNEL

Сигнал сгенерирован ядром.

Когда

SIGILL
,
SIGFPE
,
SIGSEGV
,
SIGBUS
и
SIGCHLD
посылаются ядром, то si_
code
вместо
si_kernel
принимает значения, перечисленные в табл. 12.3 [71] .

71

Он также принимает специальное значение

SIGTRAP
, которое используется отладчиками, и
SIGPOLL
, применяемое механизмом ненадежного асинхронного ввода-вывода. Ни один из них не описан в настоящей книге, поэтому подробности об этих сигналах не включены в табл. 12.3.

Таблица 12.3. Значения

si_code
для специальных сигналов

Сигнал si_code Описание
SIGILL
ILL_ILLOPC
Неправильный
код операции (opcode).
ILL_ILLOPC
Неправильный операнд.
ILL_ILLOPC
Неправильный режим адресации.
ILL_ILLOPC
Неправильная ловушка (trap).
ILL_ILLOPC
Привилегированный код операции.
ILL_ILLOPC
Привилегированный регистр.
ILL_ILLOPC
Внутренняя ошибка стека.
ILL_ILLOPC
Ошибка сопроцессора.
SIGFPE
FPE_INTDIV
Деление целого на ноль.
FPE_INTOVF
Переполнение целого.
FPE_FLTDIV
Деление числа с плавающей точкой на ноль.
FPE_FLTOVF
Переполнение числа с плавающей точкой.
FPE_FLTUND
Потеря значимости числа с плавающей точкой.
FPE_FLTRES
Неточный результат числа с плавающей точкой.
FPE_FLTINV
Неверная операция с плавающей точкой.
FPE_FLTSUB
Число с плавающей точкой вне диапазона.
SIGSEGV
SEGV_MAPPER
Адрес не отображается на объект.
SEGV_ACCERR
Неверные права доступа для адреса.
SIGBUS
BUS_ADRALN
Неверное выравнивание адреса.
BUS_ADRERR
Несуществующий физический адрес.
BUS_OBJERR
Специфичный для объекта сбой оборудования.
SIGCHLD
CLD_EXITED
Дочерний процесс завершен.
CLD_KILLED
Дочерний процесс уничтожен.
CLD_DUMPED
Дочерний процесс уничтожен с выводом дампа памяти в файл.
CLD_TRAPPED
Дочерний процесс достиг точки останова.
CLD_STOPPED
Дочерний процесс приостановлен.

Чтобы помочь прояснить разные значения, которые может принимать

si_code
, рассмотрим пример, в котором
SIGCHLD
генерируется четырьмя разными способами:
kill
,
sigqueue
,
raise
(использует системный вызов
tkill
) и созданием дочернего процесса, который немедленно прерывается.

 1: /* sicode.с */

 2:

 3: #include <sys/signal.h>

 4: #include <stdlib.h>

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