2012-12-18 19 views
2

我正在使用Unix上的C++。信号处理程序和本地状态

说我有一个长时间运行的函数来执行某些操作,例如从文件中读取数据并解析它。在这个函数中,我将从文件中读取的东西保存在局部变量num_read中。

我想在自定义信号处理程序中捕获CTRL + c并打印num_read的值。

我能想到的唯一方法是在堆上分配num_read并将其地址存储在可由我的信号处理程序访问的全局变量中。有没有更优雅的方式?

+0

你有什么Unix? – zaufi

+0

OS X和Debian。 – adrianN

回答

2

答案是否定的。有没有 之间的信号处理程序和除全局 变量之外的其余代码之间进行通信的方式。

此外,您只能在 信号处理程序中执行非常非常有限数量的操作。例如,您不能在std::ostream, 上使用<<,也不能使用printf。在Unix下处理信号的 的通常方式是在单独的 线程中捕获它们。替代方案(也适用于其他操作系统)为 ,用于定义全局变量sig_atomic_t,该变量设置在 信号处理程序中,并在主循环中轮询。 (在你的情况, 例如,你可能每次更新 num_read时间轮询吧)

+1

或者,对于讨厌线程(我!)的unix人来说,更传统的处理信号的方式是使用自我管道......更好!保证以及select()循环被唤醒(有一堆竞争条件与唤醒wait()循环的全局标志方法,需要一些sigsuspend/sigprocmask杂技)。我总是推荐一种自我管道,以提高其便携性,坚固性和完全避免所有细微问题。 –

+0

@NicholasWilson我同意线程经常被滥用,但他们确实有用。对于OP所要做的事情,sig_atomic_t标志在很大程度上是足够的,它甚至可以移植到非Unix系统。而当你需要做一些复杂的事情,并且没有方便的地方进行投票时,使用单独的线程才是真正的唯一途径。对于中间情况......我从来没有听说过从信号写入管道,但这听起来像是一个很好的妥协。 –

+0

unix解决信号问题的“传统”解决方案早在线程来到unix之前,更不用说pthread了!自我管理技巧是一个绝对的经典,既非常简单,也避免了所有的竞争条件。我当然不能写一个基于标志的解决方案的实现,而不检查手册并做一些大脑弯曲;如果信号在检查后立即触发,那么主循环不会被唤醒,并且不会很快检查标志?另一方面,我可以在头顶上写一个自我管道解决方案,它确实没有比赛和强劲。 –

2

除了传统的Unix方式与信号处理,还有其它:

  • 因为Linux内核2.6.22有signalfd()函数存在。您可以获取常用文件描述符并对其进行轮询(使用selectepoll)以获取传入信号。所以,当你处理一个信号没有适当的给他们任何限制 - 它只是平常用户空间代码,这样你就可以调用任何你想要的...
  • 据我知道OS X,有类似的功能目前在kqueue(搜索本网站或因特网为EVFILT_SIGNALkqueue