Троан Эрик В.
Шрифт:
50:
51: if (!fork) exit(0);
52: sleep(60);
53:
54: return 0;
55: }
Если
si_code
равно SI_USER
, SI_QUEUE
или SI_TKILL
, то доступны два дополнительных члена siginfo_t
: si_pid
и si_uid
, которые представляют идентификатор процесса, пославшего сигнал и действительный идентификатор пользователя этого процесса. Когда ядром посылается
SIGCHLD
, доступны члены si_pid
, si_status
, si_utime
и si_stime
. Первый из них, si_pid
, задает идентификатор процесса, состояние которого изменилось [72] . Информация о новом состоянии доступна как в si_code
(как показано в табл. 12.3) и в si_status
, что идентично целому значению состояния, возвращаемому семейством функций wait
.72
Вспомните, что
SIGCHLD
посылается не только при завершении дочернего процесса, но и при его приостановке или возобновлении работы. Последние два члена,
si_utime
и si_stime
, определяют период времени, которое потрачено дочерним приложением на работу в пользовательском режиме и в режиме ядра, соответственно (это подобно тому, что возвращают вызовы wait3
и wait4
в структуре struct rusage
). Это время измеряется в тиках часов, заданных целым числом. Количество тиков в секунду задает макрос _SC_CLK_TCK
, определенный в <sysconf.h>
. SIGSEGV
, SIGBUS
, SIGILL
и SIGFPE
— все они представляют si_addr
, специфицирующий адрес, который вызвал сбой, описанный si code
. Ниже приведен простой пример проверки контекста сигнала. Он устанавливает обработчик сигнала для
SIGSEGV
, который печатает контекст сигнала и прерывает процесс. Нарушение сегментации генерируется попыткой обращения к NULL
. 1: /* catch-segv.c */
2:
3: #include <sys/signal.h>
4: #include <stdlib.h>
5: #include <stdio.h>
6:
7: void handler(int signo, siginfo_t *info, void *f) {
8: printf("перехват");
9: if (info->si_signo == SIGSEGV)
10: printf("segv accessing %p", info->si_addr);
11: if (info->si_code == SEGV_MAPERR)
12: printf("SEGV_MAPERR");
13: printf("\n");
14:
15: exit(1);
16: }
17:
18: int main {
19: struct sigactin act;
20:
21: act.sa_sigaction = handler;
22: sigemptyset(&act.sa_mask);
23: act.sa_flags = SA_SIGINFO;
24: sigaction(SIGSEGV, &act, NULL);
25:
26: *((int *)NULL) = 1 ;
27:
28: return 0;
29: }
12.7.2. Отправка данных с сигналом
Механизм
siginfo_t
также позволяет сигналам, которые посылают программы, присоединять к себе один элемент данных (этот элемент может быть указателем, что позволяет неявно передавать любой необходимый объем данных). Чтобы отправить данные, используется union sigval
. #include <signal.h>
union sigval {
int sival_int;
void *sival_ptr;
};
Любой из членов объединения —
sival_int
или sival_ptr
— может быть установлен в требуемое значение, которое включается в siginfo_t
, доставляемое вместе с сигналом. Чтобы сгенерировать сигнал с union sigval
, должна использоваться функция sigqueue
.