2012-03-04 90 views
3

有人可以解释为什么我们不应该从信号处理程序调用非异步函数吗?就像在用这种功能调用时破坏程序的确切步骤一样。 而且,信号是否总是在单独的堆栈上运行?如果是这样,它是一个单独的上下文,或者它在信号线程的上下文上运行? 最后,在多线程系统的情况下,当信号处理程序被执行并且一些其他线程被发信号并调用相同的信号处理程序时会发生什么?我试图发展对信号及其应用的深刻理解。信号处理 - 异步函数和多线程应用程序,信号栈

回答

2

当进程接收到一个信号,它是在方法的上下文中进行处理。您应该只使用信号处理程序内的同步安全函数或重入函数。例如,您不能在信号处理程序中调用malloc()或printf()。原因是:

*)让我们假设你的进程在malloc中执行,当你收到信号。所以全局堆数据结构处于不一致的状态。现在,如果您从信号处理程序中获取堆锁并进行更改,则会进一步渲染堆不一致。

*)另一种可能是,如果堆锁已被您的进程在接收到信号时获取,然后您从信号处理程序中调用malloc(),则会看到该锁被保持并等待无限获取锁定(无限制,因为可以释放锁的线程在信号完全处理之前不会运行)。

2)信号在过程的上下文中运行。至于信号堆栈,你可以看看这个答案 - >Do signal handers have a separate stack?

3)至于获得同一信号的多个实例,你可以看看这个链接 - >Signal Handling in UNIX哪里Rumple Stiltskin回答得很好。

+0

详细阐述第一点,信号是半软件中断,因此会异步到达。内核在线程中断时保存一些寄存器(所以它会知道回到哪里等),运行处理程序然后返回。信号处理程序中的阻塞调用可能会导致死锁,因为您无法控制此类信号何时到达。这就是说,还有其他可能导致这种僵局的行为,以及许多避免它们的选择。但即使可以避免死锁,在信号环境中做太多处理也是一种不好的做法(与中断相同)。 – EdwardH 2012-03-05 07:59:24

0

我知道一些Solaris。所以我正在使用它的细节。 LWP ==用于“thread”的Solaris与pthread一样。

像SIGILL这样的陷阱信号被传送到导致陷阱的线程。异步信号被传送到第一个活动线程(LWP),或不阻塞该信号的进程。称为aslwp()的内核模块遍历进程头表(具有关联的LWP),寻找第一个可能的候选接收异步信号。

信号栈位于内核中。我不确定什么/如何回答你的信号栈问题。 一个进程可能有几个未决信号。你是这个意思吗?

发往某个进程的每个信号都保存在该进程中,直到该进程将上下文(或强制)切换到活动状态。这部分是因为当进程上下文被换出并且进程没有任何cpu方式时,通常不会产生陷阱。你当然可以招致异步信号。但是如果无法运行,该进程不能对任何信号“做任何事情”。所以,此时内核将上下文交换回活动状态,并通过aslwp()传递信号。

实时信号的行为不同,我让它留下来。

尝试阅读本:

developers.sun.com/solaris/articles/signalprimer.html