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

有帮助吗?

解决方案

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

signal() 界面它有利于古代(因此可用性),它在C标准中定义。然而,它有许多不希望的特性, sigaction()避免 - 除非你使用显式添加到 sigaction()的标志,以允许它忠实地模拟旧的 signal()行为。

  1. signal()函数不会(必然)阻止当前处理程序执行时其他信号到达; sigaction()可以阻止其他信号,直到当前处理程序返回。
  2. signal()函数(通常)将信号操作重置为几乎所有信号的 SIG_DFL (默认值)。这意味着 signal()处理程序必须重新安装自己作为其第一个操作。它还会在检测到信号和重新安装处理程序之间打开一个漏洞窗口,在此期间,如果信号的第二个实例到达,则会发生默认行为(通常是终止,有时带有偏见 - 也称为核心转储)。 / LI>
  3. signal()的确切行为因系统而异[—并且标准允许这些变化。
  4. 这些通常是使用 sigaction()而不是 signal()的充分理由。但是, sigaction()的界面无疑更加繁琐。

    无论你使用哪两个,都不要受到替代信号接口的诱惑,例如 sighold() sigignore() sigpause() sigrelse() 。 它们名义上是 sigaction()的替代品,但它们几乎没有标准化,并且存在于POSIX中以便向后兼容而不是严格使用。请注意,POSIX标准表明它们在多线程程序中的行为是未定义的。

    多线程程序和信号是另一个复杂的故事。在

    Cornstalks 观察

      

    signal() 说:

         

       未指定 signal() 在多线程进程中的效果。

         

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

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

      

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

其他提示

它们是OS信号设施的不同接口。人们应该更喜欢使用sigaction来发出信号,因为signal()具有实现定义(通常易于竞争)的行为,并且在Windows,OS X,Linux和其他UNIX系统上表现不同。

请参阅安全说明了解详情。

对我来说,下面的这一行足以决定:

  

sigaction()函数提供了一个   更全面可靠   控制信号的机制;新   应用程序应该使用sigaction()   而不是signal()

http://pubs.opengroup.org/onlinepubs/009695399/功能/ signal.html#tag_03_690_07

无论您是从头开始还是修改旧程序,sigaction应该是正确的选择。

signal()是标准C,sigaction()不是。

如果你能够使用(也就是说,你在POSIX系统上),那么使用sigaction();未指定signal()是否重置处理程序,这意味着要进行处理,您必须在处理程序内再次调用signal()。更糟糕的是,有一场比赛:如果您快速连续获得两个信号,而第二个信号在您重新安装处理程序之前交付,您将拥有默认操作,这可能会杀死您的进程。 另一方面, sigaction()保证使用“可靠”信号语义。您无需重新安装处理程序,因为它永远不会被重置。使用SA_RESTART,您还可以获得一些系统调用以自动重启(因此您无需手动检查EINTR)。 sigaction()有更多选项且可靠,因此鼓励使用它。

Psst ...不要告诉任何我告诉过你的人,但POSIX目前有一个函数bsd_signal(),它的作用类似于signal()但是给出了BSD语义,这意味着它是可靠的。它的主要用途是移植假定可靠信号的旧应用程序,POSIX不建议使用它。

来自 signal(3) 手册页:

  

说明

 This signal() facility is a simplified interface to the more
 general sigaction(2) facility.

两者都调用相同的底层工具。你可能不应该用两者来操纵单个信号的响应,但混合它们不应该导致任何破坏......

我使用signal()因为它至少在理论上更便携。我会投票给任何能够提出没有POSIX兼容层且支持signal()的现代系统的评论者。

引用 GLIBC文档

  

可以同时使用信号和sigaction功能   一个程序,但你必须小心,因为他们可以   以奇怪的方式互动。

     

sigaction函数指定的信息多于信号   功能,所以信号的返回值不能表达满   一系列的信号可能性。因此,如果你使用信号   保存并稍后重新建立动作,它可能无法执行   正确地重新建立一个使用sigaction建立的处理程序。

     

为避免出现问题,请始终使用sigaction进行保存   如果您的程序完全使用sigaction,则恢复处理程序。以来   sigaction更通用,它可以正确保存和重建任何   行动,无论是否最初建立   信号或信号。

     

在某些系统上,如果您使用信号建立动作,然后   用sigaction检查它,你得到的处理程序地址可能不会   与你用信号指定的相同。它甚至可能不是   适合用作信号的动作参数。但你可以依靠   用它作为sigaction的论据。这个问题从未发生过   在GNU系统上。

     

因此,您最好使用其中一种或另一种机制   始终在一个单一的计划中。

     

便携性注意:基本信号功能是ISO C的一项功能,   而sigaction是POSIX.1标准的一部分。如果你是   关注非POSIX系统的可移植性,那么你应该   改为使用信号功能。

     
    

版权所有(C)1996-2008 Free Software Foundation,Inc。

         

允许复制,分发和/或修改此权限     根据GNU自由文档许可条款的文档,     版本1.2或自由软件发布的任何更新版本     基础;没有不变的部分,没有封面文字,     没有封底文字。许可证的副本包含在     标题为“GNU Free Documentation License”的部分。

  

我还建议在signal()上使用sigaction(),并希望再添加一个点。 sigaction()为您提供了更多选项,例如死亡进程的pid(可能使用siginfo_t结构)。

从手册页 signal(7)

  

可以将过程导向的信号传递给任何人     其中一个当前没有阻塞信号的线程。     如果多个线程的信号未被阻塞,那么     内核选择一个任意线程来传递信号。

我会说这个“问题”适用于 signal(2) sigaction(2)。 所以要小心信号和pthreads。

...和 signal(2)似乎使用glibc在Linux下面调用 sigaction(2)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top