Если вам нужно проверить 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].
Таблица 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
4: #include
5: #include
6: #include
7:
8: #ifndef SI_TKILL
9: #define SI_TKILL -6
10: #endif
11:
12: void handler(int signo, siginfo_t *info, void *f ) {
13: static int count = 0;
14:
15: printf("перехвачен сигнал, отправленный ");
16: switch(info->si_code) {
17: case SI_USER:
18: printf("kill()\n"); break;
19: case SI_QUEUE:
20: printf("sigqueue()\n"); break;
21: case SI_TKILL:
22: printf("tkill() или raise()\n"); break;
23: case CLD_EXITED:
24: printf ("ядро сообщает, что дочерний процесс завершен\n"); exit(0);
25: }
26:
27: if (++count == 4) exit(1);
28: }
29:
30: int main() {
31: struct sigaction act;
32: union sigval val;
33: pid_t pid = getpid();
34:
35: val.sival_int = 1234;
36:
37: act.sa_sigaction = handler;
38: sigemptyset(&act.sa_mask);
39: act.sa_flags = SA_SIGINFO;
40: sigaction(SIGCHLD, &act, NULL);