【问题标题】:About the ambiguous description of sigwait()关于 sigwait() 的模棱两可的描述
【发布时间】:2011-06-13 03:06:22
【问题描述】:

如果没有信号 set 在调用时处于挂起状态,线程应为 暂停直到一个或多个成为 待办的。由 set 定义的信号 应已被阻止 调用 sigwait() 的时间;否则,行为未定义。 sigwait() 对信号的影响 集合中信号的动作是 未指定。

这真是模棱两可,pendingblock这里有什么区别?

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

总之,当需要 代码运行以响应 通知一个异步信号 线程,sigwait() 应该用于 处理信号。交替- tively,如果实现提供信号量,它们也可以是 使用,在 sigwait() 或 从信号处理例程中 以前注册 使用 sigaction()。

有人可以让sigwait的理由更合理吗?

【问题讨论】:

  • 它暂停线程的执行,直到收到指定的信号。这怎么不合理?
  • 1.这里的pending和block有什么区别?2.sigwait和sigaction怎么选,比较清楚?

标签: c linux signals


【解决方案1】:

每个进程都有一个与之关联的所谓信号掩码,它定义了被阻塞的一组信号。信号掩码可以通过setprocmask(2)(单线程代码)和pthread_sigmask(3)(多线程代码)查询或设置。

无论何时发出信号(通过kill(2)raise(3) 显式发出信号,或通过诸如分段错误引发SIGSEGV 之类的其他机制),都会根据当前信号掩码检查该信号。如果信号未被阻塞,则立即对其进行操作:如果设置,则调用相应的信号处理程序,否则运行默认操作(通常以异常状态退出或忽略它)。如果信号被信号掩码阻塞,则信号状态设置为pending,程序继续执行。

因此考虑以下示例程序:

#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

【讨论】:

  • 实际上每个线程都有一个信号掩码,不只是每个进程,pthread_sigmask 在任何线程中使用都是安全的,但sigprocmask 在多线程程序中使用可能会出现问题。
  • @R.. ,我发现另一个API sigsuspend 似乎和sigwait有相同的功能....
  • 看来两者最大的区别在于sigaction提供了一种方法,通过该方法可以将信号从外部处理到进程中的任何线程(信号捕获功能不是任何线程正常流程的一部分执行)。但是sigwait 提供了一种在一个(或多个)进程线程内直接处理信号的方法(处理是作为线程正常执行流程的一部分完成的)。这意味着使用sigwait 对处理代码的限制更少。使用sigaction 意味着处理代码仅限于“信号安全”操作。我说的对吗?
【解决方案2】:

来自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() 暂停线程的执行,直到信号未决但被阻塞。

【讨论】:

  • The signals defined by set shall have been blocked at the time of the call to sigwait(); 我们如何确保,我们是否需要运行额外的代码来确保,或者在 sigwait 中自动完成?
  • Also 来自signal(7) 手册页:“进程中的每个线程都有一个独立的信号掩码,它指示线程当前阻塞的信号集。A线程可以使用 pthread_sigmask(3) 操作其信号掩码。在传统的单线程应用程序中,可以使用 sigprocmask(2) 来操作信号掩码。"
  • @cpuer:是的,您必须使用sigprocmask 或同等工具阻止它们。 “Shall”用于表示标准对应用程序员的要求。
  • @Ignacio Vazquez-Abrams ,如果那里阻塞太多信号会导致内存浪费吗?
  • 无论信号是否被屏蔽,掩码都存在。如果您要询问未决信号被阻止,那么我无法告诉您;我不太了解内核的内部结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
  • 2016-12-16
  • 1970-01-01
  • 2013-07-31
  • 2018-08-28
  • 2014-08-12
  • 2011-04-20
相关资源
最近更新 更多