2017-02-28 53 views
0

我不认为这是重复的。我有一个非常具体的问题,当调用一个信号处理程序时,其他线程会发生什么。Linux:信号对多线程的影响

我有一个使用硬件的多线程程序。在获取SIGTERM(来自父进程)时,我希望信号处理程序将硬件的状态设置为给定状态,然后退出(1)。我明白,因为我没有使用信号掩码,所以主线程会处理信号。但是它是一个多处理器系统(树莓派),其他线程都以高优先级运行。他们可能是睡着了,但他们也可能会碰到硬件。

如果所有其他线程在信号到达时冻结,我很好 - 我直接从信号处理程序调用exit(),其他线程永远不会再运行。但是如果它们可以独立运行,那么在处理程序中设置了所需的状态之后,但在退出之前,它们可能会与硬件有关。而且我找不到描述效果的文档。如果“冻结一切,但信号处理程序”不是默认的,是否有办法获得该行为?

我可以重新设计代码,将所有硬件处理放在一个线程中,并让该线程处理中断,但这很不方便 - 我现在拥有的线程布局做了很好的分工,每个线程都知道它可以使用哪些硬件触摸和什么时候。我宁愿不重新设计。

回答

1

其他线程将在信号处理线程运行时继续运行。我不知道任何冻结一切机制。

但是,如果你有多个线程操纵硬件,看起来你应该有某种互斥机制。实际上:

pthread_mutex_lock(&hardware_lock); 
fiddle_with_hardware(); 
pthread_mutex_unlock(&hardware_lock); 

然后,你可以有你的信号处理线程获取锁,重置硬件状态,并呼吁exit没有释放锁。调用exit将终止所有线程,并且由于锁被保持,在终止之前没有其他线程能够与硬件混淆。

如果您有多个线程全部操纵整个硬件状态的离散部分,则可以为每个状态部分创建一个单独的锁。然后让您的信号处理线程在设置最终硬件状态并调用exit之前获取锁的所有的所有。由于在普通操作中,将只有一个线程试图访问状态的每个离散部分,因此额外的锁定应该没有可衡量的性能影响。

另一件事。我认为这是不准确的,“因为我没有使用信号掩模,主线程会处理信号。”从pthreads(7)

根据POSIX.1,处理向信号(使用kill(2)发送,例如)应该由进程内的单个,任意选择的线程来处理。

这意味着你应该使用pthread_sigmask以确保SIGTERM指向主线程。

+0

不过,在信号处理程序中不能做到“让你的信号处理线程获得锁定”,但在信号处理程序中使用互斥体是不安全的。 – nos

+0

@nos好点。最好让信号处理程序设置一个标志,并在从信号处理程序返回后执行其余的操作。 –

+0

这就是我所害怕的。我知道我无法做互斥体解决方案(我的担心之一是wiringPi在封面下使用了互斥体,这将使任何解决方案无法单线程访问硬件)。我可能不得不重新设计。谢谢。 – user15001