2

我正在编写具有许多独立线程的应用程序。虽然我在那里做的是相当低级别的危险事情,但线程可能会失败(SIGSEGV、SIGBUS、SIGFPE),但它们不应该杀死整个进程。有没有办法以正确的方式做到这一点?

目前我拦截上述信号,然后在它们的信号处理程序中调用 pthread_exit(NULL)。它似乎有效,但由于 pthread_exit 不是异步信号安全功能,我有点担心这个解决方案。

我知道将此应用程序拆分为多个进程可以解决问题,但在这种情况下,这不是一个可行的选择。

编辑:我知道由于忽略 SIGSEGV/SIGBUS/SIGFPE 而可能发生的所有 Bad Things™(我在低级系统和内核编程方面经验丰富),所以请尝试回答我的特定问题而不是给我关于可靠性的课程。

4

2 回答 2

1

低延迟代码设计涉及仔细的“注意您运行的系统”类型的编码部署。这意味着,例如,标准IPC 机制(例如,使用 SysV msgsnd/msgget在进程之间传递消息,或pthread_cond_wait/pthread_cond_signal在 PThreads 端)以及普通锁定原语(自适应互斥体)将被视为相当慢......因为它们涉及需要数千个 CPU 周期的东西……即上下文切换。

相反,使用“热-热”切换机制,例如破坏者模式——生产者和消费者都在紧密的循环中旋转,永久轮询单个或最坏情况下少数原子更新的内存位置,这些位置说明下一个项目的位置-be-processed 被发现和/或标记已处理的项目完成。将所有生产者/消费者绑定到单独的 CPU 内核,以便它们永远不会进行上下文切换。

在这种类型的用例中,无论您是使用单独的线程(并通过共享相同地址空间的所有线程隐式获得内存共享)还是单独的进程(并通过使用共享内存来显式地获得内存共享) -processed 以及队列 mgmt “元数据”)几乎没有什么区别,因为 TLB 和数据缓存“总是很热”(您永远不会进行上下文切换)。

如果您的“处理器”不稳定和/或没有保证完成时间,则无论如何都需要添加“收割机”机制来处理失败/超时消息,但这种垃圾收集机制必然会引入抖动(延迟峰值)。那是因为你需要一个系统调用来确定一个特定的线程或进程是否已经退出,即使在最好的情况下,系统调用延迟也只有几微秒。

从我的角度来看,您正在尝试在这里混合油和水;您需要使用未专门为低延迟部署/不受您控制的库代码而编写的库代码,以及使用纳秒延迟进行消息调度的要求。没有办法让例如pthread_cond_signal()给你 nsec 延迟,因为它必须执行系统调用来唤醒目标,这需要更长的时间。

如果你的“处理程序代码”依赖于“丰富”的环境,并且在这些和主程序之间共享了大量的“状态”......这听起来有点像在说“我需要让蒸汽驱动的飞机休息”音障”……

于 2013-07-16T10:02:47.460 回答
1

正确的方法是让整个过程结束,然后开始另一个过程。您没有解释为什么这不合适,但从本质上讲,这是对各种讨厌的极端情况完全安全的唯一方法(这可能适用于您的情况,也可能不适用)。

我不知道任何不涉及让整个过程的 100% 安全的方法。(还要注意,有时只是从这些错误中继续的行为是“未定义的行为”——这并不意味着你肯定会摔倒,只是它可能是一个问题)。

当然,有人可能知道一些有效的巧妙技巧,但我很确定唯一 100% 保证的方法是杀死整个过程。

于 2013-07-15T23:12:45.157 回答