日期:2014-05-16  浏览次数:20714 次

信号阻塞函数sigsuspend()的使用。
调用后sigsuspend(&waitmask),信号SIGINT被屏蔽。执行程序后,输入ctrl+c(SIGINT),没有标准输出,
但继续输入ctrl+\(SIGQUIT)后,会同时输出“quit signal”和“interrupt”。这是为什么?
[code=C/C++][/code]
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
void sig_int(int);
volatile sig_atomic_t quitflag=0;
int main()
{
  sigset_t newmask,waitmask,oldmask;
  signal(SIGINT,sig_int);
  signal(SIGQUIT,sig_int);

  sigemptyset(&waitmask);
  sigaddset(&waitmask,SIGINT);
  sigemptyset(&newmask);
  sigaddset(&newmask,SIGQUIT);

  sigprocmask(SIG_BLOCK,&newmask,&oldmask);
   
  while(quitflag == 0)
  sigsuspend(&waitmask);
   
  sigprocmask(SIG_SETMASK,&oldmask,NULL);
  exit(0);
}

void sig_int(int signo)
{
  if (signo == SIGINT)
  printf("interrupt\n");
  else if (signo == SIGQUIT)
  {
  //quitflag = 1;
  printf("quit signal\n");
  }
  return;
}

------解决方案--------------------
sigsuspend调用后放掉了SIGQUIT,阻塞了SIGINT.

所以,

你杀SIGINT, 安然不动, 信号被阻塞.
你杀SIGQUIT, 被处理, 设置了变量, sigsuspend返回.

sigsupend返回后放掉SIGINT, 阻塞SIGQUIT, 所以SIGINT信号被处理, 打印.
------解决方案--------------------
sigsuspend的期间,你的waitmask是阻塞了SIGINT,,,所以你按下ctrl+c发出SIGINT信号后,
此信号处于未决状态。
然后你又发出SIGQUIT信号,此信号没被阻塞,,所以触发handler,,
然后根据上面的因为描述sigsuspend在handler返回后,也返回

前面没注意有个while(1)无限循环。。

注意: sigsuspend返回后,会恢复原来的阻塞情况,这时SIGINT没被阻塞,,而SIGQUIT被阻塞。
所以之前未决的SIGINT信号,在sigsuspend返回后,循环再次执行sigsuspend前,SIGINT会激活handler处理。