关于sigwait()的含糊描述

时间:2011-06-13 03:06:22

标签: c linux signals

  

如果没有信号          在调用时,set是挂起的,线程应该是   暂停直到一个或多个成为   悬而未决。由set定义的信号   应该被封锁了          调用sigwait()的时间;否则,行为未定义。   sigwait()对信号的影响   集合中信号的动作是   未指定的。

这真的很模糊,pendingblock之间的区别是什么?

关于如何在sigwaitsigaction之间进行选择的结论尚不清楚:

  

总之,当有必要时   代码运行以响应   异步信号通知   应该使用thread,sigwait()   处理信号。 Alterna-          如果实现提供了信号量,它们也可以   使用,遵循sigwait()或   来自信号处理程序   以前注册过          与sigaction()。

有人可以说sigwait更合理吗?

2 个答案:

答案 0 :(得分:22)

每个进程都有一个与之关联的信号掩码,它定义了阻塞的信号集。可以使用setprocmask(2)(对于单线程代码)和pthread_sigmask(3)(对于多线程代码)查询或设置信号掩码。

无论何时发出信号(通过kill(2)raise(3)明确提出,或通过其他一些机制,如分段故障引发SIGSEGV),都会针对当前信号检查信号面具。如果信号未被阻止,则立即对其进行操作:如果设置则调用相应的信号处理程序,否则运行默认操作(通常以异常状态退出或忽略它)。如果信号被信号掩码阻止,则信号状态设置为挂起,程序继续执行。

请考虑以下示例程序:

#include <signal.h>
#include <stdio.h>

void on_sigusr1(int sig)
{
  // Note: Normally, it's not safe to call almost all library functions in a
  // signal handler, since the signal may have been received in a middle of a
  // call to that function.
  printf("SIGUSR1 received!\n");
}

int main(void)
{
  // Set a signal handler for SIGUSR1
  signal(SIGUSR1, &on_sigusr1);

  // At program startup, SIGUSR1 is neither blocked nor pending, so raising it
  // will call the signal handler
  raise(SIGUSR1);

  // Now let's block SIGUSR1
  sigset_t sigset;
  sigemptyset(&sigset);
  sigaddset(&sigset, SIGUSR1);
  sigprocmask(SIG_BLOCK, &sigset, NULL);

  // SIGUSR1 is now blocked, raising it will not call the signal handler
  printf("About to raise SIGUSR1\n");
  raise(SIGUSR1);
  printf("After raising SIGUSR1\n");

  // SIGUSR1 is now blocked and pending -- this call to sigwait will return
  // immediately
  int sig;
  int result = sigwait(&sigset, &sig);
  if(result == 0)
    printf("sigwait got signal: %d\n", sig);

  // SIGUSR1 is now no longer pending (but still blocked).  Raise it again and
  // unblock it
  raise(SIGUSR1);
  printf("About to unblock SIGUSR1\n");
  sigprocmask(SIG_UNBLOCK, &sigset, NULL);
  printf("Unblocked SIGUSR1\n");

  return 0;
}

输出:

SIGUSR1 received!
About to raise SIGUSR1
After raising SIGUSR1
sigwait got signal: 30
About to unblock SIGUSR1
SIGUSR1 received!
Unblocked SIGUSR1

答案 1 :(得分:4)

来自signal(7)手册页:

Signal Mask and Pending Signals
    A  signal  may  be  blocked,  which means that it will not be delivered
    until it is later unblocked.  Between the time when it is generated and
    when it is delivered a signal is said to be pending.

“等待”和“被阻止”不是相互排斥的。

同样来自signal(7)手册页:

Synchronously Accepting a Signal
    Rather than asynchronously catching a signal via a signal  handler,  it
    is  possible to synchronously accept the signal, that is, to block exe-
    cution until the signal is delivered, at which point the kernel returns
    information about the signal to the caller.  There are two general ways
    to do this:

    * sigwaitinfo(2), sigtimedwait(2),  and  sigwait(3)  suspend  execution
      until  one  of  the signals in a specified set is delivered.  Each of
      these calls returns information about the delivered signal.

因此sigaction()用于允许其他代码在信号挂起之前运行,而sigwait()暂停执行该线程,直到信号挂起但被阻止。