sigaction 和 signal 和有什么不一样? [英] What is the difference between sigaction and signal?

查看:48
本文介绍了sigaction 和 signal 和有什么不一样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正准备向我们这里的应用程序添加一个额外的信号处理程序,但我注意到作者使用了 sigaction() 来设置其他信号处理程序.我打算使用 signal().为了遵循惯例,我应该使用 sigaction() 但如果我从头开始编写,我应该选择哪个?

I was about to add an extra signal handler to an app we have here and I noticed that the author had used sigaction() to set up the other signal handlers. I was going to use signal(). To follow convention I should use sigaction() but if I was writing from scratch, which should I choose?

推荐答案

使用 sigaction() 除非你有非常令人信服的理由不这样做.

Use sigaction() unless you've got very compelling reasons not to do so.

signal() 接口它具有古老性(因此具有可用性),并且在 C 标准中进行了定义.然而,它有许多 sigaction() 避免的不良特性 - 除非您使用显式添加到 sigaction() 的标志以允许它忠实地模拟旧的 >signal() 行为.

The signal() interface has antiquity (and hence availability) in its favour, and it is defined in the C standard. Nevertheless, it has a number of undesirable characteristics that sigaction() avoids - unless you use the flags explicitly added to sigaction() to allow it to faithfully simulate the old signal() behaviour.

  1. signal() 函数不会(必然)在当前处理程序执行时阻止其他信号的到达;sigaction() 可以阻塞其他信号,直到当前处理程序返回.
  2. signal() 函数(通常)将几乎所有信号的信号操作重置回 SIG_DFL(默认).这意味着 signal() 处理程序必须重新安装自己作为它的第一个操作.它还在检测到信号和重新安装处理程序之间打开了一个漏洞窗口,在此期间,如果信号的第二个实例到达,则默认行为(通常终止,有时带有偏见 - 又名核心转储)发生.
  3. signal() 的确切行为因系统而异 - 标准允许这些变化.
  1. The signal() function does not (necessarily) block other signals from arriving while the current handler is executing; sigaction() can block other signals until the current handler returns.
  2. The signal() function (usually) resets the signal action back to SIG_DFL (default) for almost all signals. This means that the signal() handler must reinstall itself as its first action. It also opens up a window of vulnerability between the time when the signal is detected and the handler is reinstalled during which if a second instance of the signal arrives, the default behaviour (usually terminate, sometimes with prejudice - aka core dump) occurs.
  3. The exact behaviour of signal() varies between systems — and the standards permit those variations.

这些通常是使用 sigaction() 而不是 signal() 的充分理由.然而,sigaction() 的接口无疑更加繁琐.

These are generally good reasons for using sigaction() instead of signal(). However, the interface of sigaction() is undeniably more fiddly.

无论您使用这两者中的哪一个,都不要被替代信号接口所诱惑,例如sighold(),sigignore(),sigpause()sigrelse().它们名义上是 sigaction() 的替代品,但它们只是勉强标准化并且出现在 POSIX 中是为了向后兼容而不是认真使用.请注意,POSIX 标准表示它们在多线程程序中的行为是未定义的.

Whichever of the two you use, do not be tempted by the alternative signal interfaces such as sighold(), sigignore(), sigpause() and sigrelse(). They are nominally alternatives to sigaction(), but they are only barely standardized and are present in POSIX for backwards compatibility rather than for serious use. Note that the POSIX standard says their behaviour in multi-threaded programs is undefined.

多线程程序和信号是另一个复杂的故事.AFAIK,signal()sigaction() 在多线程应用中都可以.

Multi-threaded programs and signals is a whole other complicated story. AFAIK, both signal() and sigaction() are OK in multi-threaded applications.

玉米秸秆 观察:

signal() 说:

signal() 在多线程进程中的效果是不确定的.

因此,我认为 sigaction() 是唯一可以在多线程进程中安全使用的方法.

Thus, I think sigaction() is the only that can be used safely in a multi-threaded process.

这很有趣.在这种情况下,Linux 手册页比 POSIX 更具限制性.POSIX 为 signal() 指定:

That's interesting. The Linux manual page is more restrictive than POSIX in this case. POSIX specifies for signal():

如果进程是多线程的,或者如果进程是单线程的并且执行信号处理程序而不是作为结果:

If the process is multi-threaded, or if the process is single-threaded and a signal handler is executed other than as the result of:

  • 调用abort()raise()kill()pthread_kill()的进程,或 sigqueue() 生成未被阻塞的信号
  • 一个挂起的信号被解除阻塞并在解除阻塞的调用返回之前被传递
  • The process calling abort(), raise(), kill(), pthread_kill(), or sigqueue() to generate a signal that is not blocked
  • A pending signal being unblocked and being delivered before the call that unblocked it returns

如果信号处理程序引用除 errno 之外的任何具有静态存储持续时间的对象,而不是通过为声明为 volatile sig_atomic_t 的对象赋值,则行为未定义,或者如果信号处理程序调用本标准中定义的任何函数,而不是 信号概念.

the behavior is undefined if the signal handler refers to any object other than errno with static storage duration other than by assigning a value to an object declared as volatile sig_atomic_t, or if the signal handler calls any function defined in this standard other than one of the functions listed in Signal Concepts.

所以POSIX明确规定了signal()在多线程应用中的行为.

So POSIX clearly specifies the behaviour of signal() in a multi-threaded application.

尽管如此,sigaction() 基本上在所有情况下都是首选——并且可移植的多线程代码应该使用 sigaction() 除非有压倒性的理由为什么它可以't(例如仅使用标准 C 定义的函数"——是的,C11 代码可以是多线程的).这基本上就是这个答案的开头段落所说的.

Nevertheless, sigaction() is to be preferred in essentially all circumstances — and portable multi-threaded code should use sigaction() unless there's an overwhelming reason why it can't (such as "only use functions defined by Standard C" — and yes, C11 code can be multi-threaded). Which is basically what the opening paragraph of this answer also says.

这篇关于sigaction 和 signal 和有什么不一样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆