2011-12-21 37 views
0

我看到在我的应用程序were not always working as expected信号量。然后我被告知,当信号中断sem_wait呼叫时,可能会导致此意外行为。什么照顾信号的存在

所以,我的问题是程序员在有信号时需要注意什么。对于sem_wait,我们可以检查返回值,但对于所有非异步安全函数,这是否一样?当期望信号中断我们的代码时,我们还应该记住什么?

回答

2

UNIX信号是一种蠕虫病毒,只是为了说明这一点。

有2个关于系统调用和信号的阵营。

  • 的SysV/POSIX语义:系统调用被信号中断,他们返回一个错误,并设置errno为EINTR
  • BSD语义的系统调用是如果发生信号自动重新启动(当然,其中大部分是无论如何,一些不是,例如select/poll/sleep)。

使用signal()时,缺省值为上述两者之一,BSD系统和Linux默认为BSD语义,并且每个人[需要的引用]都具有SysV语义。 (在Linux上,这取决于很多因素,例如用-std = C99编译给人SysV的语义,与-std = gnu99给BSD语义。例如参见http://www.gnu.org/s/hello/manual/libc/Interrupted-Primitives.html

当您安装使用sigaction的信号处理器()您可以选择使用SA_RESTART标志的语义。

基本上是:

  • 不要使用信号,如果你能帮助它。
  • 如果可以,请使用BSD语义。
  • 对于需要可移植并处理信号的代码,您需要将每个系统调用包装在一个循环中,以检查调用失败,检查errno是否为EINTR并再次执行系统调用(或者根据捕获信号)。
  • 库调用可以使用信号,即使您的代码没有。
  • 系统调用通常使用SysV/Posix语义,将返回-1并将errno设置为EINTR。但请阅读文档以了解错误情况。

编辑:编辑,因为我混淆了BSD vs Sysv语义。

+0

因此,如果SysV自动重新启动一个系统调用,那么为什么sem_wait没有得到重新启动,因为它有时会给出错误代码? – MetallicPriest 2011-12-21 12:15:43

+0

@MetallicPriest你是否100%肯定它不?无论如何,我希望有一个列表,确切地说哪些系统调用不是自动重新启动的,即使是使用sysv语义。 sem_wait可能就是其中之一。 – user964970 2011-12-21 12:19:16

+0

对于任何给定系统调用的默认中断操作应记录在系统的联机帮助页中。如果您使用的是Linux系统,并且没有发生任何异常情况,那么您的系统调用应该在被信号中断后透明地重新启动。 – 2011-12-21 14:18:58