【发布时间】:2011-10-20 09:53:55
【问题描述】:
我想确切地知道异步信号处理程序的执行在 Linux 上是如何工作的。首先,我不清楚 哪个 线程执行信号处理程序。其次,我想知道使线程执行信号处理程序所遵循的步骤。
关于第一件事,我读过两种不同的、看似矛盾的解释:
-
Linux 内核,作者 Andries Brouwer,§5.2 "Receiving signals" states:
当信号到达时,进程被中断,当前寄存器被保存,信号处理程序被调用。当信号处理程序返回时,被中断的活动继续进行。
-
StackOverflow question "Dealing With Asynchronous Signals In Multi Threaded Program" 让我认为 Linux 的行为是 like SCO Unix's:
当一个信号被传递给一个进程时,如果它被捕获,它将由一个且只有一个满足以下条件的线程处理:
在sigwait(2) 系统调用中阻塞的线程,其参数确实包含捕获信号的类型。
信号掩码不包含捕获信号类型的线程。
其他注意事项:
- sigwait(2) 中阻塞的线程优先于未阻塞信号类型的线程。
- 如果多个线程满足这些要求(可能有两个线程正在调用sigwait(2)),那么将选择其中一个。这种选择是应用程序无法预测的。
- 如果没有线程符合条件,则信号将在进程级别保持“待处理”,直到某个线程符合条件为止。
另外,"The Linux Signals Handling Model" by Moshe Bar states“异步信号被传递到第一个发现没有阻塞信号的线程。”,我解释为信号被传递到具有其 sigmask not 的某个线程,包括信号。
哪个是正确的?
关于第二个问题,所选线程的堆栈和寄存器内容会发生什么变化?假设 thread-to-run-the-signal-handler T 正在执行 do_stuff() 函数。线程 T 的堆栈是否直接用于执行信号处理程序(即信号蹦床的地址被压入 T 的堆栈,控制流转到信号处理程序)?或者,是否使用了单独的堆栈?它是如何工作的?
【问题讨论】:
-
This 可能会回答您的一些问题(绝对不是全部)。
标签: c linux signals signal-handling