Linux программирование в примерах
Часть 144 из 253 Информация о книге
Когда в
установлен флагact->sa_flags, полеSA_SIGINFOявляется указателем на функцию, объявленную следующим образом:act->sa_sigactionvoid action_handler(int sig, siginfo_t *info, void *context) {/* Здесь тело обработчика */}Структура
_t предоставляет изобилие сведений о сигнале:siginfo/* Определение POSIX 2001. Действительное содержание может на разных системах быть разным. */typedef struct {int si_signo; /* номер сигнала */int si_errno; /* значение <errno.h> при ошибке */int si_code; /* код сигнала; см. текст */pid_t si_pid; /* ID процесса, пославшего сигнал */uid_t si_uid; /* настоящий UID посылающего процесса */void *si_addr; /* адрес вызвавшей ошибку инструкции */int si_status; /* значение завершения, может включать death-by-signal */long si_band; /* связывающее событие для SIGPOLL/SIGIO */union sigval si_value; /* значение сигнала (расширенное) */} siginfo_t;Поля
,si_signoиsi_codeдоступны для всех сигналов. Другие поля могут быть членами объединения, поэтому должны использоваться лишь для тех сигналов, для которых они определены. В структуреsi_valueмогут быть также и другие поля.siginfo_tПочти все поля предназначены для расширенного использования. Все подробности содержатся в стандарте POSIX и справочной странице sigaction(2). Однако, мы можем описать простое использование поля
.si_codeДля
,SIGBUS,SIGCHLD,SIGFPE,SIGILL,SIGPOLLиSIGSEGVполе si_code может принимать любое из набора предопределенных значений, специфичных для каждого сигнала, указывая на причину появления сигнала. Откровенно говоря, детали несколько чрезмерны; повседневному коду на самом деле нет необходимости иметь с ними дела (хотя позже мы рассмотрим значения дляSIGTRAP). Для всех остальных сигналов членSIGCHLDимеет одно из значений из табл. 10.4.si_codeТаблица 10.4. Значения происхождения сигнала для
si_code
Значение Только GLIBC Смысл SI_ASYNCIOАсинхронный ввод/вывод завершен (расширенный). SI_KERNEL√ Сигнал послан ядром. SI_MESGQСостояние очереди сообщений изменилось (расширенный.) SI_QUEUEСигнал послан из (расширенный).sigqueue()SI_SIGIO√ поставлен в очередь (расширенный).SIGIOSI_TIMERВремя таймера истекло SI_USERСигнал послан функцией .kill()иraise()также могут его вызвать, но это не обязательно.abort()В особенности полезно значение
; оно позволяет обработчику сигнала сообщить, был ли сигнал послан функциямиSI_USERилиraise()(описываются далее). Вы можете использовать эту информацию, чтобы избежать повторного вызоваkill()илиraise().kill()Третий аргумент обработчика сигнала с тремя аргументами,
t, является расширенной возможностью, которая больше не обсуждается в данной книге.void *contexНаконец, чтобы увидеть
в действии, исследуйте полный исходный код обработчика сигнала дляsigaction():sort.c2074 static void2075 sighandler(int sig)2076 {2077 #ifndef SA_NOCLDSTOP /* В системе старого стиля... */2078 signal(sig, SIG_IGN); /* - для игнорирования sig используйте signal()*/2079 #endif - /* В противном случае sig автоматически блокируется */20802081 cleanup(); /* Запуск кода очистки */20822083 #ifdef SA_NOCLDSTOP /* В системе в стиле POSIX... */2084 {2085 struct sigaction sigact;20862087 sigact.sa_handler = SIG_DFL; /* - Установить действие по умолчанию */2088 sigemptyset(&sigact.sa_mask); /* - Нет дополнительных сигналов для блокирования */2089 sigact.sa_flags = 0; /* - Специальные действия не предпринимаются */2090 sigaction(sig, &sigact, NULL); /* - Поместить на место */2091 }2092 #else /* На системе в старом стиле... */2093 signal(sig, SIG_DFL); /* - Установить действие по умолчанию */2094 #endif