9

我处于需要读取信号处理程序(SIGSEGV信号处理程序,据我所知是每个线程库)内的二叉搜索树(BST)的情况。BST 可以被应用程序中的其他线程修改。

现在,由于信号处理程序不能使用信号量、互斥锁等,因此无法访问共享数据,我该如何解决这个问题?请注意,我的应用程序是多线程的,并且在多核系统上运行。

4

4 回答 4

4

我可以看到两个非常干净的解决方案:

  1. Linux 特有的:创建一个专门的线程处理信号。使用signalfd()捕获信号。这样,您将在常规线程中处理信号,而不是任何有限的处理程序。
  2. 便携:还使用一个专用线程,该线程在收到信号之前一直处于休眠状态。您可以使用管道创建一对文件描述符。线程可以从第一个描述符中读取(2),并且在信号处理程序中,您可以将(2)写入第二个描述符。根据POSIX ,在信号处理程序中使用 write() 是合法的。当线程从管道中读取某些内容时,它知道它必须执行一些操作。
于 2012-12-02T16:58:45.617 回答
4

您不应该从信号处理程序访问共享数据。您可以在以下文章中找到有关信号的更多信息:

面向应用程序员的 Linux 信号

Linux 信号处理模型

所有关于 Linux 信号

到目前为止,看起来在 linux 中处理信号最安全的方法是 signalfd。

于 2011-12-13T16:15:48.490 回答
3

假设 SH 不能直接访问共享数据,那么也许你可以间接地做到这一点:

  1. 有一些只有信号处理程序可以写入的全局变量,但可以从其他地方读取(即使只在同一个线程中)。
  2. SH 在调用时设置标志
  3. 线程不在修改 BST 的过程中轮询该标志;当找到它设置时,它们执行原始信号所需的处理(使用任何必要的同步),然后发出不同的信号(如 SIGUSR1)以指示处理完成
  4. SH for THAT 信号重置标志

如果您担心重叠的 SIGSEGV,请在混合中添加一个计数器以跟踪。(嘿!你刚刚建立了自己的信号量!)

这里的薄弱环节显然是轮询,但它是一个开始。

于 2011-12-13T16:18:44.950 回答
1

您可能会考虑mmap -ing保险丝文件系统(在用户空间中)。

实际上,您会更喜欢支持外部寻呼机的Gnu Hurd

也许您在信号处理程序中读取二叉搜索树的技巧通常可以在实践中工作,不可移植并且以依赖于内核版本的方式。也许使用低级不可移植技巧(例如futexesatomic gcc builtins)序列化访问可能会起作用。阅读 NPTL 的(特定于机器的)源代码,即当前的 Linux pthread 例程应该会有所帮助。

可能的情况是pthread_mutex_locketc 实际上可以从 Linux 信号处理程序内部使用......(因为它可能只做futex原子指令)。

于 2011-12-13T17:53:29.830 回答