Linux 关于sigwait()的模糊描述

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6326290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 04:28:58  来源:igfitidea点击:

About the ambiguous description of sigwait()

clinuxsignals

提问by cpuer

If no signal in set is pending at the time of the call, the thread shall be suspended until one or more becomes pending. The signals defined by set shall have been blocked at the time of the call to sigwait(); otherwise, the behavior is undefined. The effect of sigwait() on the signal actions for the signals in set is unspecified.

如果在调用时 set 中没有信号挂起,线程应挂起,直到一个或多个挂起。set 定义的信号应该在调用 sigwait() 时被阻塞;否则,行为未定义。未指定 sigwait() 对 set 中信号的信号操作的影响。

This is really ambiguous ,what's the difference between pendingand blockhere?

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

And its conclusion on how to choose between sigwaitand sigactionis not clear at all:

其关于如何在sigwait和之间进行选择的结论sigaction根本不清楚:

In summary, when it is necessary for code run in response to an asynchronous signal to notify a thread, sigwait() should be used to handle the signal. Alterna- tively, if the implementation provides semaphores, they also can be used, either following sigwait() or from within a signal handling routine previously registered with sigaction().

总之,当代码需要运行以响应异步信号以通知线程时,应该使用 sigwait() 来处理该信号。或者,如果实现提供了信号量,它们也可以在 sigwait() 之后使用,或者在之前使用 sigaction() 注册的信号处理例程中使用。

Can someone make the reason of sigwaitmore rational?

有人可以使原因sigwait更合理吗?

采纳答案by Adam Rosenfield

Every process has what's called a signal maskassociated with it, which defines the set of signals which are blocked. The signal mask can be queried or set with setprocmask(2)(for single-threaded code) and pthread_sigmask(3)(for multithreaded code).

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

Whenever a signal is raised (either explicitly via kill(2)or raise(3), or via some other mechanism such as a segmentation fault raising SIGSEGV), the signal is checked against the current signal mask. If the signal is not blocked, then it is acted upon immediately: the corresponding signal handler is called if set, otherwise the default action (typically exiting with abnormal status or ignoring it) is run. If the signal is blocked by the signal mask, then the state of the signal is set to pending, and the program continues execution.

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

So consider the following example program:

因此,请考虑以下示例程序:

#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;
}

Output:

输出:

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

回答by Ignacio Vazquez-Abrams

From the signal(7)man page:

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 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.

"Pending" and "blocked" are not mutually exclusive.

“待处理”和“已阻止”并不相互排斥。

Also from the signal(7)man page:

同样来自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.
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.

So sigaction()is used to allow other code to run until a signal is pending, whereas sigwait()suspends execution of the thread until a signal is pending but blocked.

Sosigaction()用于允许其他代码运行直到信号挂起,而sigwait()挂起线程的执行直到信号挂起但被阻塞。