LinuxC信号-进程间通信方式之一

1.信号特性:
  简单但不可靠,不能携带大量信息,特定条件才触发。
  包括软件中断和硬件中断。
    软件中断如:调用abort、raise,alarm,setitimer等函数触发的中断
    硬件中断如:除0导致的SIGFPE(浮点数例外),非法访问内容导致的SIGSEGV(段错误),非法内容对齐等导致的总线错误(SIGBUS) 等等

2.信号三要素:
  1)编号:信号编号范围是1~64。1~31为常规信号编号。34-64为实时信号。
  2)事件:同时每个编号对应一个触发事件。如1->SIGHUP,2->SIGINT,3->SIGQUIT,... man 7 signal 可查看全部信号。
       常见对应事件:Ctr+c 产生SIGINT(2),Ctrl+ 产生SIGQUIT(3),Ctrl+z 产生SIGTSTP(20),
       除0操作 产生SIGFPE(8)浮点数例外,非法访问内存 产生SIGSEGV(11)段错误,非法内存对齐等 产生SIGBUS(7)总线错误
  3)默认动作:包括 Term终止进程,Ign忽悠,Core终止进程并生成Core文件,Stop暂停进程,Cont继续进行。
        注意:SIGKILL(9)和SIGSTOP(19)信号不允许被屏蔽、忽略、捕捉等,只能执行默认动作。SIGKILL默认终止进程,SIGSTOP默认暂停进程。

3.常见信号产生函数
  kill(pid,sig)函数:发送sig信号。pid>0给指定进程 发送sig信号,pid=0给同组进程 发送sig信号,pid<-1给指定进程组 发送sig信号,pid=-1给所有进程 发送sig信号。
  raise(sig) 函数:给当前进程发送sig信号。
  abort() 函数:给当前进程发送SIGABRT信号。
  alarm(sec) 函数:sec大于0时表示sec秒后给当前进程发送SIGALRM信号。sec=0表示取消定时器。每个进程只有唯一一个定时器。
  setitimer() 函数:周期定时器,which可选:ITIMER_REAL(自然定时,产生SIGALRM信号)、ITIMER_VIRTUAL(虚拟用户空间计时,产生SIGVTALRM信号)、ITIMER_PROF(运行时计时,产生SIGPROF信号)
          
4.信号集
  未决信号集:产生了但还没决定处理的待处理信号集合。未决就是没决定的意思嘛。
  阻塞信号集:一般称为信号屏蔽字mask。用来告诉内核屏蔽哪些信号,也就是说告诉内核哪些信号屏蔽掉不处理。
  内核是通过读取未决信号集来判断信号是否应该被处理的,信号屏蔽字mask可以影响未决信号集合。我们可以通过程序修改mask的值达到屏蔽指定信号的目的。
  简单理解:就是所有未处理的信号,经过信号屏蔽字筛选后,剩下的就是未决信号集.

5.常见信号集操作函数
  sigset_t:信号集类型,是一个unsigned long类型。没错,是一个基本数据类型,但表示一个信号集合,说明是按位操作。
  sigemptyset(sigset_t *set)    函数:将set集合按位清空为0
  sigfillset(sigset_t *set)     函数:将set集合按位填充为1
  sigaddset(sigset_t *set,signum) 函数:将signum信号添加到set集合
  sigdelset(sigset_t *set,signum) 函数:将signum信号从set集合删除
  sigismember(sigset_t,signum)   函数:判断signum信号是否在set集合里
    注意:sigaddset()、sigdelset()、sigismember()等函数调用之前必须先调用sigemptyset()或者sigfillset()函数初始化信号集。
  sigprocmask(int how,sigset_t *set,sigset_t *oldset)    函数:用来屏蔽、解除屏蔽某个信号,本质是读取并修改PCB(在进程内核里)里的信号屏蔽字mask。
    how:为SIG_BLOCK时,set表示需要屏蔽的信号,相当于mask=mask|set,"或"操作
       为SIG_UNBLOCK时,set表示需要解除的信号,相当于mask=mask&~set,"取反"后再"与"操作
       为SIG_SETMASK时,set表示用于替换之前的信号屏蔽字,相当于mask=set,set成为新的信号屏蔽字。
    set:传入参数,需要操作的信号集
    oldset:传出参数,返回之前的信号集额,一般用于恢复时使用。
  sigpending(sigset_t *set):    函数:读取当前进程的未决信号集,set为传出参数。
  pause()  函数:主动挂起,处于阻塞状态,等等任一信号送达唤醒,该信号不能是被屏蔽的,不然没法送达呀。
  sigsuspend  函数:挂起等待信号。类似于pause函数,但pause有时序问题,可以使用sigsuspend函数解决时序问题。
  sigqueue  函数:对应kill函数,信号传参,携带union参数。传递指针的话,本进程内才有意义。因为每个进程都有自己独立的空间,进程间传递指针是没有意义的。
  
6.信号捕捉函数
  signal(signum,handler)函数:
    捕捉指定的signum信号,触发回调handler函数。handler是一个函数指针。由于历史原因,兼容性较差,很少使用。
  sigaction(signum,struct sigaction *act,struct sigaction *oldact)函数
    捕捉指定的signum信号,回调函数再act结构体里。act为传入参数,新的处理方式。oldact为传出参数,返回旧的处理方式,一般用于之前恢复处理方式时使用。
    struct sigaction{
      void (*sa_handler)(int);//信号捕捉后的处理函数,也可以指定为SIG_IGN表示忽悠,SIG_DEL表示默认处理方式
      void (*sa_sigaction)(int,siginfo_t*,void*);//sa_flags指定为SA_SIGINFO时信号捕捉后改为调用该函数,不调用sa_handler函数
      sigset_t sa_mask;//处理函数执行期间(可能执行很长时间呀)的信号屏蔽字,表示处理函数执行期间屏蔽哪些信号
      int sa_flags;//特定标识位,通常为0表示默认属性
      void (*sa_restorer)(void);//已过时,已弃用
    }
    处理函数执行期间,屏蔽字由sa_mask指定,默认情况下处理函数执行期间,被捕捉信号自动屏蔽,常规信号不支持排队,多次产生同一信号可能只产生一次触发

7.SIGCHLD信号
  子进程终止时,或者子进程收到SIGSTOP信号暂停时,或者子进程收到SIGCONT信号后继续运行时,都会发送该信号。

  


原文地址:https://www.cnblogs.com/yongfengnice/p/11953839.html