读取信号处理程序中的共享数据

我正处在一个需要在信号处理程序( SIGSEGV信号处理程序,根据我的知识是每个线程库)内部读取二进制search树(BST)的情况。 BST可以被应用程序中的其他线程修改。

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

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

应用程序员的Linux信号

Linux信号处理模型

所有关于Linux信号

看起来像目前处理信号的最安全的方法是signalfd。

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

  1. 有一些全局变量,只有信号处理程序可以写入,但可以从别处读取(即使只在同一个线程中)。
  2. SH在被调用时设置标志
  3. 线程轮询这个标志,当他们不在修改BST的时候; 当找到它的时候,他们做原始信号所需要的处理(使用任何需要的同步),然后产生一个不同的信号(如SIGUSR1)来表示处理完成
  4. THAT信号的SH重置标志

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

这里的薄弱环节显然是投票,但这是一个开始。

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

  1. 特定于Linux:创建一个专用的线程处理信号。 使用signalfd()捕捉信号。 这样你就可以在普通的线程中处理信号,而不是任何有限的处理器。
  2. 便携式:也使用一个专门的线程睡觉,直到收到信号。 您可以使用管道来创建一对文件描述符。 线程可以从第一个描述符中读取(2),在一个信号处理程序中可以写入(2)到第二个描述符。 根据POSIX ,在信号处理程序中使用write()是合法的。 当线程从管道读取内容时,它知道它必须执行一些操作。

您可能会考虑使用熔丝文件系统(在用户空间中)。

事实上,对于外部寻呼机支持的Gnu Hurd ,你会更开心

也许你在你的信号处理程序中阅读二叉搜索树的方法经常可以在实践中,不可移植地和依赖于内核版本的方式工作。 也许序列化访问与低层次的非移植技巧(例如futexes和原子GCC内置 )可能工作。 阅读NPTL的(机器特定的)源代码,即当前的Linux pthread例程应该有所帮助。

这可能是pthread_mutex_lock等实际上可以从Linux信号处理程序中使用的情况…(因为它可能只是futex和原子指令)。