关于标准信号的传递

时间:2011-06-14 13:02:35

标签: c linux signals

  

相比之下,如果有多个实例   标准信号是              当该信号当前被阻止时传送,然后只有一个   实例排队。

我认为以上描述并不是那么清楚,并且对我造成了歧义:

如果特定信号不是阻塞,那么同一信号的多个实例会排队吗?

排队的信号,特定于流程的位置或全球位置在哪里?

如何处理排队信号,是否可以同时处理两个信号,或者保证信号将被逐个处理?

所以这里实际上是3个问题..

4 个答案:

答案 0 :(得分:8)

  

如果特定信号未被阻止,同一信号的多个实例会排队吗?

这取决于是否使用sigaction结构和sigaction()函数为信号设置了SA_SIGINFO标志,以及您的系统是否具有_POSIX_REALTIME_SIGNALS(现代Linux内核)的有效定义。如果两个实例均为真,那么符合这两个条件的任何到达信号将在每个进程队列中排队,直到它们被递送或接受,直到操作系统对给定信号队列中的项目数量施加的限制。在此之后,任何其他到达该信号类型的信号都将被丢弃。

如果这些情况中的任何一个不成立,则仅处理当前到达的信号,并且在当前信号处理程序运行时到达的相同信号类型的任何其他信号被丢弃。此外,如果您阻止信号,并且两个或更多信号到达过程并且未被传递,则它们被合并为单个信号事件。但同样,只有在不满足上述两个条件的情况下才会这样做......否则会将多个相同类型的信号事件排队。

还有一点需要注意......所述的两个条件是针对POSIX规范,但是Linux将排队任何实时信号,即使没有为该信号设置SA_SIGINFO。这意味着任何信号对应于范围SIGRTMIN和SIGRTMAX。

  

排队的信号,特定于流程的位置或全球位置在哪里?

它存储在每个进程的队列中。

  

如何处理排队信号,   两个信号是否可能   正在处理中   时间,或它的保证信号会   一个接一个地处理?

这取决于您使用sigaction struture和sigaction()函数设置信号处理程序的方式。在信号处理程序运行时,无法保证阻止任何其他信号。有一个信号掩码可以在sigaction结构内设置,确定信号处理程序运行时阻塞的信号。信号本身被阻塞,直到信号处理程序完成,但如果没有被sigaction结构中设置的信号处理程序设置的信号掩码阻止,则不同的信号可以中断当前的信号处理程序。因此,您在信号处理程序中执行的任何操作都应该是异步安全的,并且您不应该在fprintf()等信号处理程序中调用任何非异步安全函数。因此可以保证信号本身得到处理按FIFO顺序(即,信号不会自行中断),但如果您没有故意阻止它们,其他信号可能会中断您当前的信号处理程序。请记住,在信号处理程序中设置信号掩码以阻止其他信号中断处理程序是非常糟糕的想法,并且不是原子操作,所以不要这样做。如果您希望在信号处理程序运行时阻止其他信号,请在传递给sigaction的{​​{1}}结构中提供信号掩码。

答案 1 :(得分:3)

这是位掩码 - 请注意标准信号的值都在32下?

编辑0:

标准信号的“队列”只是每个线程的一个位掩码,因此一旦信号发布但尚未传送,则设置给定位,并且在该位被清除之前发送相同的信号,即信号交付。

编辑1:

我们可以可靠地收获子进程,因为该机制不依赖于信号。内核保存有关进程祖先的详细信息,子进程一旦退出就不会消失,但留在进程表中供父进行收获(这就是我们如何繁殖僵尸,对吧:)。等待SIGCHLD表示“至少有一个孩子改变了状态,进入内核收集尸体”。这里的竞争不在信号“队列”上,而是在进程表/树/任何内容上,而内核的工作就是保护它。

答案 2 :(得分:2)

每个线程中一次处理一个信号。信号处理程序运行时,所有其他信号都会自动阻止。

因此,不可能将多个相同的信号排队到单个线程。但是,许多不同的信号可以出现在队列中。

我认为信号处理程序可能会在信号退出之前解除阻塞,在这种情况下,如果信号生成,您可能会冒信号堆栈溢出(用于信号处理程序的调用堆栈,而不是信号队列)比他们处理得快。

答案 3 :(得分:1)

如果在处理相同信号时传递信号,则在从当前调用返回后立即再次调用处理程序,因此将有多个信号传递。

当然,如果信号在仍然处理第一个信号的同时被多次发送,则只有一个信号将被排队,并且只会发生一次重复的处理程序调用。

在内核的proc结构中,信号被标记为“待定”,因此每个进程都有单独的信号位掩码,并且每种类型只有一个信号(SIGBUS,SIGINT,SIGUSR1等)可以挂起,但是几个不同的信号可能是同时等待。