訊號處理與訊號()
訊號編號可以是同步的(如 SIGSEGV
- 分段故障),當它們由程式本身的故障觸發時,或者非同步(如 SIGINT
-互動式注意),當它們從程式外部啟動時,例如通過按鍵作為 Cntrl-C
。
signal()
功能是 ISO C 標準的一部分,可用於分配處理特定訊號的功能
#include <stdio.h> /* printf() */
#include <stdlib.h> /* abort() */
#include <signal.h> /* signal() */
void handler_nonportable(int sig)
{
/* undefined behavior, maybe fine on specific platform */
printf("Catched: %d\n", sig);
/* abort is safe to call */
abort();
}
sig_atomic_t volatile finished = 0;
void handler(int sig)
{
switch (sig) {
/* hardware interrupts should not return */
case SIGSEGV:
case SIGFPE:
case SIGILL:
Version >= C11
/* quick_exit is safe to call */
quick_exit(EXIT_FAILURE);
Version < C11
/* use _Exit in pre-C11 */
_Exit(EXIT_FAILURE);
default:
/* Reset the signal to the default handler,
so we will not be called again if things go
wrong on return. */
signal(sig, SIG_DFL);
/* let everybody know that we are finished */
finished = sig;
return;
}
}
int main(void)
{
/* Catch the SIGSEGV signal, raised on segmentation faults (i.e NULL ptr access */
if (signal(SIGSEGV, &handler) == SIG_ERR) {
perror("could not establish handler for SIGSEGV");
return EXIT_FAILURE;
}
/* Catch the SIGTERM signal, termination request */
if (signal(SIGTERM, &handler) == SIG_ERR) {
perror("could not establish handler for SIGTERM");
return EXIT_FAILURE;
}
/* Ignore the SIGINT signal, by setting the handler to `SIG_IGN`. */
signal(SIGINT, SIG_IGN);
/* Do something that takes some time here, and leaves
the time to terminate the program from the keyboard. */
/* Then: */
if (finished) {
fprintf(stderr, "we have been terminated by signal %d\n", (int)finished);
return EXIT_FAILURE;
}
/* Try to force a segmentation fault, and raise a SIGSEGV */
{
char* ptr = 0;
*ptr = 0;
}
/* This should never be executed */
return EXIT_SUCCESS;
}
使用 signal()
會對訊號處理程式中允許的內容施加重要限制,請參閱備註以獲取更多資訊。
POSIX 建議使用 sigaction()
而不是 signal()
,因為它具有不明確的行為和重要的實現變化。POSIX 還定義了比 ISO C 標準更多的訊號 ,包括 SIGUSR1
和 SIGUSR2
,它們可以由程式設計師自由地用於任何目的。