在程序执行过程中,需要自己用 kill 随机触发 RTMIN+1(35)信号,每次触发该信号时,都会打印
[signal] enter signal handler.
从程序的运行结果可以看得出来,对于 Thread1而言,虽然表面上它不做任何事情,但实际上,它在运行过程中,会因为信号的到来跳转至信号函数运行;因为信号函数由 Thread1运行,处在与 MainThread平行的状态,所以如果 MainThread(即主函数)处于临界区访问时,信号函数会一直等待到 MainThread退出临界区才继续运行,这样它们都有被系统调度运行的机会,于是不会造成死锁的问题。
似乎,到现在对于信号与锁的问题得到了圆满的解决,但是如果我们扩展一下思路,将 Linux 系统对实时信号的处理特性扩展到多线程信号处理的情况下,就是我下面的扩展。
多线程信号并行处理机制的实现
设想现在有一个这样的应用:由于需要处理的信号比较多,出于对效率的考虑,如果能够将信号的处理并行化,将有效的提高程序的效率。如何编写这样的模型呢?基于双线程的一些讨论,我们可以得到以下理论模型,如图 3:
图 3. 多线程信号处理模型
在这个模型中,程序中存在多个线程,当有多个信号同时抵达时,系统会随机的选择其中一个线程完成信号的处理,当一个线程正在处理这个信号时,新抵达的信号并不会被屏蔽,而是被分配给下一个可以处理信号的线程,同时由于信号处理的过程是在线程运行空间内完成的,这样在各个线程处理信号的过程中就达到了一个并行的目的,根据重入性的需要,在处理函数中使用锁来达到互斥的目的。因此这个模型可以大大提高信号的处理能力,其同时可处理信号的个数将等于线程的数量,根据应用的需要,对于 SMP 系统应该根据 CPU 的数目确定线程的数目。
对于这个模型的实现程序,请读者自行实践,本文限于篇幅不给出详细的代码。而最简单的实现方法即是在方案 2 提供的程序中加入一个新的空线程。
总结
本文针对信号函数、锁及重入性问题进行一些有益的探讨,通过单线程程序、信号函数之间重入性的矛盾引入,扩展到 Linux 对于多线程程序信号函数处理的行为对双线程程序与信号重入性的影响,最后引申到多线程程序并行信号处理模型。本文中提供了解决在信号函数中调用不可重入程序片段矛盾的方法,希望为使用信号函数的开发人员提供有益的参考。