在Linux/ c++中,发送给线程/进程的信号是否使其变为活动状态?

In Linux/C++, does a signal sent to a thread/process make it become active?

本文关键字:是否 信号 活动状态 线程 c++ Linux 进程      更新时间:2023-10-16

在Linux中,当信号被发送到进程/线程(无论出于何种原因)时,是否立即调用信号处理程序(假设有一个,并且信号没有被阻塞)?

我的意思是,我很确定在处理信号的进程/线程中,它将立即被调用,但我的意思是相对于其他进程/线程。

如果处理程序被立即调用,它是否也会使相应的进程/线程活动(以便其正常执行立即继续)?

编辑

由于我最初的问题似乎被误解了,我将试着用一个例子再次解释。

假设在我的计算机中,我有一个CPU,有两个进程在运行,进程a和进程B。并假设它们都没有阻塞系统调用(如sleep)。通常,我猜,操作系统会在执行进程A和进程B之间切换,在一小段时间之后(例如,执行进程A 100毫秒,然后执行进程B 100毫秒,然后再次执行进程A 100毫秒,等等)。假设进程'A'现在是活动进程(即它现在占用CPU)。现在假设进程'A'向进程'B'发送了一个信号(或者,不管出于什么原因,操作系统将这个信号发送给进程'B')。进程'B'已经为该信号注册了一个处理程序,并且没有阻塞它。所以问题是,操作系统现在会立即停止执行进程'A'并切换到执行进程'B'的信号处理程序吗?如果答案是肯定的,那么它之后会立即继续执行进程'B'(正常代码,而不是信号处理程序),还是切换回执行进程'A',并且只在一小段时间后恢复执行进程'B'?

同样的问题也可以问线程而不是进程。

不,仅在上下文切换时发送信号。在此之前,所有信号都将排队。在许多相同类型的信号中,通常只有一个信号被送到目的地。因此,我可以放心地说,破坏的信号比传递的信号要多。我建议您查阅有关任何unix书籍的章节。我最喜欢的是了解linux内核和linux内核开发。如果你还需要技术帮助,请评论

有两种情况:当发出信号的进程处于活动状态时,以及当它被阻塞时。

对于前一种情况,根据http://www.tldp.org/LDP/tlk/ipc/ipc.html,进程将在退出系统调用时处理信号。这意味着像a = b+c这样的正常指令(或其等效的机器码)不会因为信号而中断。信号处理也可能在cpu密集型进程中被延迟。

然而,当进程被阻塞时,它取决于被调用的内核函数是否是可中断的(例如,wait_event_interruptible)。如果它是可中断的,进程将被唤醒,否则,直到它离开不可中断函数(例如,由于IRQ),它才会被唤醒。

是的,处理程序将立即被调用。假设我有一个编码如下的进程:

#include <stdio.h>
#include <signal.h>
void handle_signal(int signal);
volatile int i = 1;
int main( )
{
    struct sigaction sa;
    // Setup the sighub handler
    sa.sa_handler = &handle_signal;
    // Block every signal during the handler
    sigfillset(&sa.sa_mask);
    while(1)
    {
        if(i == 1)
        {
            printf("A");
        }
    }
    return 0;
}
void handle_signal(int signal) {
    /*
     * Please note that printf et al. are NOT safe to use in signal handlers.
     * Look for async safe functions.
     */
    const char *signal_name;
    sigset_t pending;
    // Find out which signal we're handling
    switch (signal) {
        case SIGHUP:
            signal_name = "SIGHUP";
            break;
        case SIGSTOP:
            i = 0;
            signal_name = "SIGSTOP";
            break;
        case SIGCONT:
            signal_name = "SIGCONT";
            i = 1;
            break;
        default:
            fprintf(stderr, "Caught wrong signal: %dn", signal);
            return;
    }
}

在shell上一直打印A,除非它接收到SIGSTOP信号。因此,打开外壳,执行kill -STOP <pid of above process>
验证进程已停止,然后从shell使用kill -CONT <pid of above process>

发送SIGCONT信号

And if the handler is called immediately, will it also make the corresponding process/thread active (so that its normal execution continues immediatly)

你的信号处理程序有自己的上下文。所以没有线程必须被激活来处理你的信号。但有一些问题必须牢记在心。如果您的线程正在等待一些系统调用,如sleepread/write或任何其他阻塞操作,则该系统调用将被中断,该调用的返回值将向您提供您的进程(而不是线程)的信息。已收到信号。返回值是EINTR。如果您的线程只是在运行或睡眠,而没有等待系统调用,则不会发生任何其他事情!简单地说,调用处理程序时,进程内的线程调度不会发生任何变化。