2011-12-13 123 views
8

我在一个情况下,我需要阅读的信号处理器(SIGSEGV信号处理程序,据我所知这是每个线程基地)内的二叉搜索树(BST)内共享数据。 BST可以由应用程序中的其他线程修改。读信号处理程序

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

+5

我会努力想办法不读取该信号处理程序中的共享数据。 – dbeer

+1

为了强调@dbeer的要点,在信号处理程序中,您通常不应该做任何会阻止或引发其他信号或任何冗长操作的任何操作。信号处理程序应该很小,很快且很短。 –

+1

也许我错过了一些东西,但是如果只有程序的线程访问共享内存(没有其他中断和异常),为什么不使用信号量(不管它是不错的风格是一个不同的问题)?如果一个线程访问关键区域,阻塞它,被另一个线程休眠,信号量仍然被锁定为另一个线程,并且最终您的初始线程将被安排再次访问它。除了性能方面的原因,我认为既没有数据损坏的危险,也没有拖延系统。 – gnometorule

回答

3

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

  1. 具有唯一信号处理程序可以编写一些全局变量,但可以从其他地方读取(甚至如果只在同一个线程内)。
  2. SH在被调用时设置标志
  3. 线程轮询该标志,当它们不在修改BST时;当找到它时,它们进行原始信号所需的处理(使用任何需要的同步),然后产生一个不同的信号(如SIGUSR1)来表示处理已完成
  4. SH THAT信号复位标志

如果你担心重叠SIGSEGVs,计数器加进来跟踪。 (嘿!你刚刚建立了你自己的信号量!)

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

+0

我在想同样的事情:-p!但是当一个线程在信号发生时修改BST会发生什么。这一点有点令人担忧。 – MetallicPriest

+0

我认为这不会是一个问题:信号会被抓住,设置标志并返回;该线程将继续修改BST,并且不会尝试“处理”信号,直到完成修改为止。假设这种修改是原子的,那看起来是一个合理的结果。 –

1

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

其实,你会在Gnu Hurd更幸福这对于external pagers

或许你在你的信号处理函数读二叉搜索树砍支持往往可以在实际工作中,非便携和内核版本依赖的方式。也许序列化访问与低级别的非便携式技巧(例如futexesatomic gcc builtins)可能工作。阅读NPTL(特定机器)的源代码,即当前的Linux pthread例程应该有所帮助。

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

+0

我提到了一些非移动技巧和Gnu赫德... –

3

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

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