如果在处理过程中收到另一个信号,信号处理程序将如何工作?

How exactly signal handler will work if it receives another signal while processed?

我试图测试信号处理程序中到底发生了什么。

int num = 0;

void    handler(int signum, siginfo_t *sip, void *ptr)
{
    sleep(1);
    num ++;
    write(1, "processs!\n", 10);
}

int main(void)
{
    int pid = getpid();
    struct sigaction    act1;

    printf("%d\n", pid);

    //act1.sa_flags = SA_NODEFER;
    act1.sa_sigaction = &handler;
    sigaction(SIGUSR1, &act1, NULL);
    sigaction(SIGUSR2, &act1, NULL);
    while (1)
    {
        sleep(1);
        printf("%d\n", num);
    };
}

在其他过程中,我发送了两个信号,如下所示: 杀死(pid,SIGUSR1); 杀死(pid,SIGUSR1);

据我所知,信号处理程序会阻塞调用其自身的信号..... 并在处理程序结束后处理阻塞的信号。我希望处理程序将被调用两次并且全局变量 num 将为 2;

但只调用了一次,num 为 1。

然后我尝试像这样发送两个不同的信号: 杀死(pid,SIGUSR1); 杀死(pid,SIGUSR2);

据我所知,SIGUSR2 将在处理程序仍在睡眠期间处理,并且第一个处理程序将在此处退出,并且 num ++ 将不起作用。它只会在稍后调用的处理程序中处理一次。

但是处理程序被调用了两次,在这次试验中 num 是 2....

我对信号处理程序的想法有什么误解吗?我很困惑。

这是你的误解:

and this first handler will quit here, and num ++ will not work.

当一个信号处理程序中断另一个信号处理程序时,一旦中断信号处理程序完成,被中断的信号处理程序就会从中断处恢复。它不只是提前结束。

顺便说一句,你的代码有很多问题:

  1. 由于您没有使用 SA_SIGINFO,因此您的 handler 应该只接受一个参数并且应该进入 sa_handler 而不是 sa_sigaction
  2. 您没有初始化 struct sigaction 的大部分字段,因此当您对其调用 sigaction 时,可能会发生非常奇怪的事情。
  3. 您在信号处理程序中可以执行的操作确实受到限制;特别是,您不能访问 int 类型的全局变量。将 num 更改为 volatile sig_atomic_t.
  4. 你基本上不应该在循环之外使用 write,因为部分写入基本上可以在任何时候发生。

至于为什么发送 SIGUSR1 两次并不总是 运行 处理程序两次,那是因为 non-real-time 信号允许合并,所以如果你的第二个 kill发生在第一个的信号处理程序开始 运行ning 之前,那么第二个实际上不会做任何事情。