C 关于标准信号的传递

C 关于标准信号的传递,c,linux,signals,C,Linux,Signals,相比之下,如果 标准信号是 当该信号当前被阻止时传送,则只有一个 实例已排队 我认为上述描述不太清楚,给我造成了歧义: 如果特定信号未被阻止,同一信号的多个实例是否会排队 信号排队的位置是进程特定位置还是全局位置 排队的信号是如何处理的,是否可能同时处理两个信号,或者保证信号将逐个处理 所以这里实际上有3个问题。如果在处理同一个信号的同时传递信号,那么在当前调用返回后,将再次调用处理程序,因此将有多个信号传递 当然,若在处理第一个信号的同时多次发送信号,则只有一个信号将排队,并且只会发生一次重复

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

我认为上述描述不太清楚,给我造成了歧义:

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

信号排队的位置是进程特定位置还是全局位置

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


所以这里实际上有3个问题。

如果在处理同一个信号的同时传递信号,那么在当前调用返回后,将再次调用处理程序,因此将有多个信号传递

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


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

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

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

我认为信号处理程序可能在退出之前解除对某些信号的阻止,在这种情况下,您可能会面临信号堆栈溢出的风险(用于信号处理程序的调用堆栈,而不是信号队列)如果信号的生成速度比处理速度快。

这是一个位掩码-请注意,标准信号的值都在
32

编辑0: 标准信号的“队列”只是每个线程的一个位掩码,因此,一旦发送了一个信号但尚未发送,就会设置给定的位,并且发送相同的信号会丢失,直到该位被清除,即发送信号

编辑1: 我们可以可靠地获得子进程,因为这种机制不仅仅依赖于信号。内核保留有关进程祖先的详细信息,子进程退出后不会消失,而是留在进程表中供父进程获取(这就是我们繁殖僵尸的方式,右:)。挂起
SIGCHLD
意味着“至少有一个孩子改变了状态,浸入内核收集尸体”。这里的竞争不是在信号“队列”上,而是在进程表/树/任何东西上,保护它是内核的工作

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

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

如果其中任何一种情况都不正确,则只处理当前到达的信号,并丢弃在当前信号处理程序运行时到达的相同信号类型的任何其他信号。另外,如果您正在阻塞信号,并且两个或多个信号到达该进程并且没有被传递,那么它们将合并到一个信号事件中。但是,这只是在不满足上述两个条件的情况下。。。否则,相同类型的多个信号事件将排队

还有一个提示。。。声明的两个条件适用于POSIX规范,但Linux将对任何实时信号排队,即使没有为该信号设置SA_SIGINFO。这意味着与范围SIGRTMIN和SIGRTMAX相对应的任何信号

信号排队的位置是进程特定位置还是全局位置

它存储在每个进程队列中

如何处理排队的信号, 是否可能有两个信号 正在同时进行处理 时间,或者保证信号会 一个接一个地处理

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