关于标准信号的传递

时间:2022-12-17 00:10:02

By contrast, if multiple instances of a standard signal are delivered while that signal is currently blocked, then only one instance is queued.

相反,如果在该信号当前被阻止的情况下传送标准信号的多个实例,则只有一个实例排队。

I think the above description is not so clear and causing ambiguity to me:

我认为上面的描述并不那么明确,并且对我造成了歧义:

what if the specific signal is not blocked , will multiple instances of the same signal be queued?

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

Where is the signal queued,a process specific location or a global location?

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

How is the queued signals handled, will it be possible that two signals are being processed at the same time,or it's guaranteed signals will be processed one by one?

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

So it's actually 3 questions here..

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

4 个解决方案

#1


7  

what if the specific signal is not blocked , will multiple instances of the same signal be queued?

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

It depends on whether the SA_SIGINFO flag has been set for the signal using the sigaction structure and sigaction() function, and whether your system has a valid definition for _POSIX_REALTIME_SIGNALS (modern Linux kernels do). If both instances are true, then any arriving signals that fit those two conditions will be queued in a per-process queue until they are delivered or accepted up to the limits imposed by the operating system for the number of items in a given signal's queue. After that point, any other signal arriving for that signal-type are dropped.

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

If either one of those situations is not true, then only the currently arriving signal is handled, and any other signals of the same signal type that arrive while the current signal handler is running are dropped. Also if you are blocking the signal, and two or more signals arrive at the process and are not delivered, they are merged together into a single signal event. But again, this is only if the above two conditions are not met ... otherwise multiple signal events of the same type are queued.

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

One more note ... the two conditions stated are for the POSIX specification, but Linux will queue any real-time signal, even if SA_SIGINFO is not set for that signal. So that would mean any signal corresponding to the range SIGRTMIN and SIGRTMAX.

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

Where is the signal queued,a process specific location or a global location?

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

It's stored in a per-process queue.

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

How is the queued signals handled, will it be possible that two signals are being processed at the same time,or it's guaranteed signals will be processed one by one?

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

This depends on how you setup the signal handler with the sigaction struture and sigaction() function. It is not guaranteed that any other signals will be blocked while your signal handler runs. There is a signal mask that can be set within the sigaction struture determining what signals are blocked while your signal handler runs. The signal itself is blocked until the signal handler completes, but a different signal can interrupt your current signal handler if it is not blocked by the signal mask set for the signal handler set in your sigaction strurcture. Therefore anything you do in a signal handler should be async-safe, and you should not be calling any non-async-safe functions in your signal handler like fprintf(), etc. So it is guaranteed that the signal itself is handled in FIFO order (i.e., a signal will not interrupt itself), but other signals can interrupt your current signal handler if you have not intentionally blocked them. Keep in mind that setting up a signal mask inside your signal handler in an attempt to block other signals from interrupting your handler is a very bad idea, and is not an atomic operation, so don't do that. If you want other signals blocked while your signal handler runs, provide a signal mask in the sigaction structure you pass to sigaction().

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

#2


2  

It's a bit-mask - notice that standard signals all have values under 32?

它是一个位掩码 - 注意标准信号的值都低于32?

Edit 0:

The "queue" for standard signals is just a bit-mask per thread, so once a signal is posted and not yet delivered the given bit is set, and posting the same signal is lost until that bit is cleared, i.e. signal is delivered.

标准信号的“队列”只是每个线程的比特掩码,因此一旦信号被发布但尚未传送,则给定的比特被设置,并且发送相同的信号将丢失,直到该比特被清除,即信号被传送。

Edit 1:

We can reliably reap child processes because that mechanism does not rely on signals only. Kernel keeps detailed information about process ancestry, and child process does not disappear once it exited, but left in the process table for the parent to reap (that's how we breed zombies, right :). Pending SIGCHLD means "at least one of your children changed state, dip into the kernel to collect the corpses". The race here is not on the signal "queue", but on the process table/tree/whatever and it's the kernel's job to protect it.

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

#3


1  

If signal is delivered while same signal is being handled, handler would be invoked again right after return from current invocation, so there will be multiple signal deliveries.

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

Of course, if signal is sent multiple times while still processing first one, only one signal will be queued and only one repeated handler invocation will occur.

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

Signals are marked "pending" in proc struct in kernel, so there is separate signal bitmask for each process and only one signal of each kind (SIGBUS, SIGINT, SIGUSR1, etc) can be pending, but several different signals may be pending simultaneously.

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

#4


1  

One signal is processed at a time, in each thread. While the signal handler runs, all other signals are automatically blocked.

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

So it's not possible to queue multiple of the same signal to a single thread. Many different signals, however, can appear in the queue.

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

I supposed it's possible for a signal handler to unblock some signals before it exits, in this case you would risk overflow of the signal stack (the call stack used for signal handlers, not the signal queue) if the signals were being generated faster than they could be processed.

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

#1


7  

what if the specific signal is not blocked , will multiple instances of the same signal be queued?

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

It depends on whether the SA_SIGINFO flag has been set for the signal using the sigaction structure and sigaction() function, and whether your system has a valid definition for _POSIX_REALTIME_SIGNALS (modern Linux kernels do). If both instances are true, then any arriving signals that fit those two conditions will be queued in a per-process queue until they are delivered or accepted up to the limits imposed by the operating system for the number of items in a given signal's queue. After that point, any other signal arriving for that signal-type are dropped.

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

If either one of those situations is not true, then only the currently arriving signal is handled, and any other signals of the same signal type that arrive while the current signal handler is running are dropped. Also if you are blocking the signal, and two or more signals arrive at the process and are not delivered, they are merged together into a single signal event. But again, this is only if the above two conditions are not met ... otherwise multiple signal events of the same type are queued.

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

One more note ... the two conditions stated are for the POSIX specification, but Linux will queue any real-time signal, even if SA_SIGINFO is not set for that signal. So that would mean any signal corresponding to the range SIGRTMIN and SIGRTMAX.

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

Where is the signal queued,a process specific location or a global location?

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

It's stored in a per-process queue.

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

How is the queued signals handled, will it be possible that two signals are being processed at the same time,or it's guaranteed signals will be processed one by one?

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

This depends on how you setup the signal handler with the sigaction struture and sigaction() function. It is not guaranteed that any other signals will be blocked while your signal handler runs. There is a signal mask that can be set within the sigaction struture determining what signals are blocked while your signal handler runs. The signal itself is blocked until the signal handler completes, but a different signal can interrupt your current signal handler if it is not blocked by the signal mask set for the signal handler set in your sigaction strurcture. Therefore anything you do in a signal handler should be async-safe, and you should not be calling any non-async-safe functions in your signal handler like fprintf(), etc. So it is guaranteed that the signal itself is handled in FIFO order (i.e., a signal will not interrupt itself), but other signals can interrupt your current signal handler if you have not intentionally blocked them. Keep in mind that setting up a signal mask inside your signal handler in an attempt to block other signals from interrupting your handler is a very bad idea, and is not an atomic operation, so don't do that. If you want other signals blocked while your signal handler runs, provide a signal mask in the sigaction structure you pass to sigaction().

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

#2


2  

It's a bit-mask - notice that standard signals all have values under 32?

它是一个位掩码 - 注意标准信号的值都低于32?

Edit 0:

The "queue" for standard signals is just a bit-mask per thread, so once a signal is posted and not yet delivered the given bit is set, and posting the same signal is lost until that bit is cleared, i.e. signal is delivered.

标准信号的“队列”只是每个线程的比特掩码,因此一旦信号被发布但尚未传送,则给定的比特被设置,并且发送相同的信号将丢失,直到该比特被清除,即信号被传送。

Edit 1:

We can reliably reap child processes because that mechanism does not rely on signals only. Kernel keeps detailed information about process ancestry, and child process does not disappear once it exited, but left in the process table for the parent to reap (that's how we breed zombies, right :). Pending SIGCHLD means "at least one of your children changed state, dip into the kernel to collect the corpses". The race here is not on the signal "queue", but on the process table/tree/whatever and it's the kernel's job to protect it.

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

#3


1  

If signal is delivered while same signal is being handled, handler would be invoked again right after return from current invocation, so there will be multiple signal deliveries.

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

Of course, if signal is sent multiple times while still processing first one, only one signal will be queued and only one repeated handler invocation will occur.

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

Signals are marked "pending" in proc struct in kernel, so there is separate signal bitmask for each process and only one signal of each kind (SIGBUS, SIGINT, SIGUSR1, etc) can be pending, but several different signals may be pending simultaneously.

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

#4


1  

One signal is processed at a time, in each thread. While the signal handler runs, all other signals are automatically blocked.

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

So it's not possible to queue multiple of the same signal to a single thread. Many different signals, however, can appear in the queue.

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

I supposed it's possible for a signal handler to unblock some signals before it exits, in this case you would risk overflow of the signal stack (the call stack used for signal handlers, not the signal queue) if the signals were being generated faster than they could be processed.

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