#include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <errno.h>
/*
  * signal 函数的使用方法简单,但并不属于 POSIX 标准
  *
  * 而 POSIX 标准定义的信号处理接口是 sigaction 函数
  */
#if 0
信号通常用于终止和清理,它们很少被用于编程逻辑。
typedef void (*sighandler_t)(int);
 sighandler_t signal(int signum, sighandler_t handler);
设置某一信号的对应动作
    第一个参数signum:指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。
     
     第二个参数handler:描述了与信号关联的动作,它可以取以下三种值:
        第一种是我们自己定义的信号处理函数,
         第二种是传入SIG_DFL 表示将之前signal所改变的信号处理方式还原,
         第三种是传入SIG_IGN,表示处理方式为忽略该信号,内核会直接将信号丢弃,不会传递到进程。
     signal(SIGINT, SIG_IGN);    //  忽略 CTRL + C
    #define SIG_IGN  ((__sighandler_t)1)    /* Ignore signal.  */
     #define SIG_ERR  ((__sighandler_t)-1)   /* error return from signal */
     #define SIG_DFL    ((__sighandler_t)0)  /* default signal handling */
    SIG_IGN        : 忽略
     SIG_DFL        : 恢复对信号的系统默认处理
 信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据
进程对不同的信号可以同时保留,但对于同一个信号,进程并不知道在处理之前来过多少个
     'CTRL + \ 组合键时,是产生了SIGQUIT信号'
 进程对信号的响应
     1. 忽略信号:大部分信号可被忽略,除SIGSTOP和SIGKILL信号外(这是超级用户杀掉或停掉任意进程的手段)。
      2. 捕获信号:注册信号处理函数,它对产生的特定信号做处理。
      3. 让信号默认动作起作用:unix内核定义的默认动作,有5种情况:
         a) 流产abort:终止进程并产生core文件。
         b) 终止stop:终止进程但不生成core文件。
         c) 忽略:忽略信号。
         d) 挂起suspend:挂起进程。
         e) 继续continue:若进程是挂起的,则resume进程,否则忽略此信号。
 #endif
static void signal_handler(int signo)
 {
     printf("signo %d", signo);
     exit(signo);
 }
int main()
 {
     if (signal(SIGINT, signal_handler) == SIG_ERR)
         printf("SIGINT erro");
     if (signal(SIGTERM, signal_handler) == SIG_ERR)
         printf("SIGTERM erro");
     if (signal(SIGSEGV, signal_handler) == SIG_ERR)
         printf("SIGSEGV erro");
     if (signal(SIGABRT, signal_handler) == SIG_ERR)
         printf("SIGABRT erro");
     if (signal(SIGFPE, signal_handler) == SIG_ERR)
         printf("SIGFPE erro");
     if (signal(SIGILL, signal_handler) == SIG_ERR)
         printf("SIGILL erro");
    while (1)
         sleep(2);
    return 0;
 }