【问题标题】:How to avoid the interruption of sleep calls due to a signal in Linux?如何避免 Linux 中因信号而中断睡眠调用?
【发布时间】:2010-02-08 18:04:33
【问题描述】:

我在 Linux 中使用实时信号来通知串行端口中新数据的到达。不幸的是,这会导致睡眠调用在有信号时被中断。

有人知道避免这种行为的方法吗?

我尝试使用常规信号 (SIGUSR1),但我一直得到相同的行为。

【问题讨论】:

    标签: c linux signals


    【解决方案1】:

    来自 nanosleep 手册页:

    nanosleep 将程序的执行至少延迟 *req 中指定的时间。如果已将信号传递给进程,则该函数可以更早地返回。在这种情况下,它返回 -1,将 errno 设置为 EINTR,并将剩余时间写入 rem 指向的结构中,除非 rem 为 NULL。然后可以使用 *rem 的值再次调用 nanosleep 并完成指定的暂停。

    【讨论】:

    • 我会选择这个。我看了一下 POCO 库,它们的 Thread::sleep 实现做了你描述的事情。谢谢
    • 别忘了检查您选择的答案。
    • 我不会,但我宁愿等一会儿再接受答案。
    • 我发现 Linux 上中断的nanosleep()errno 设置为ERESTARTSYS,而不是EINTR。至少如果使用sigaction()SA_RESTART 安装了信号处理程序。它没有这样记录。
    【解决方案2】:

    您可以使用sigprocmask()signal() 调用屏蔽几乎所有信号(SIGKILL 除外)。第一个将返回您以前的掩码,您可以在sleep() 之后恢复。一些例子是here。如果这没有帮助,请详细说明是什么信号中断了您的睡眠。我想,你可以额外检查一下这种情况(“睡眠被信号中断?”)并再次进入睡眠状态。

    【讨论】:

    【解决方案3】:

    较新的 Linux 内核支持 signalfd(2)。这与sigprocmask(2) 一起是在单个epoll_wait(2) 调用中结合处理信号和IO 事件的一种非常好的方法。

    【讨论】:

    • 这是一种非常丑陋且不可移植的方法,即使对遗留系统(自管道技巧)或所有现代 POSIX 兼容系统(使用 @987654324 @)。
    • 便携性是一个光荣的目标,但并不总是首要的目标。
    • 在这种情况下可移植的唯一原因是过早的优化,这是万恶之源。有一大群 Linux 羊为了性能而鼓吹epoll,而除非您一次处理数十万个文件描述符,否则普通的poll 永远不会成为您的瓶颈(即使那样,它也几乎肯定不会成为)。不要喝可乐。
    • 好的,如果你指出一种等待文件描述符 信号的便携方式,我会很高兴地离开牛群(请注意,我不是在谈论性能:)。
    • 适用于所有遗留系统的经典方法是让您的信号处理程序只将一个字节写入管道,并将管道的读取端包含在您的 fd_set for @987654328 @。或者,如果您对 POSIX 感到满意,您可以保持信号被阻塞,并在 pselect 等待期间使用 pselect 以原子方式解除阻塞。然后,您可以在pselect 返回后检查信号处理程序设置的全局标志,以查看接收到的信号。请注意,如果您使用普通的select 并自己取消阻止/阻止信号,则会出现严重的竞争情况,信号会丢失。
    【解决方案4】:

    如果你不想被打扰,为什么要使用实时信号?

    在某个地方,无论是在 Rockind 的“高级 Unix 编程”还是 Steven 的书中,都有一个如何伪造这一点的示例。您在开始睡眠之前记下当前的 time_t。睡眠结束后,检查以确保所需的时间已经过去,如果没有,则开始新的睡眠。将 sleep 置于一个循环中,该循环计算要走的时间并休眠该数量,并在所需时间过去后退出。

    【讨论】:

    • 如果系统时钟发生变化,就会出现各种与此相关的问题。这就是为什么 POSIX 提供比 sleep 调用更复杂的时钟功能的原因,这可能应该完全放弃......
    【解决方案5】:

    嗯,实时信号应该会中断睡眠。您可以改用非实时信号。另一种方法是检查预期的睡眠时间是否已经过去,如果没有,则在剩余的时间间隔内睡眠。

    【讨论】:

    • 感谢您的回答,但使用常规信号也会中断睡眠呼叫。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 2011-05-02
    • 2014-09-11
    • 2014-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多