信号的进一步认识

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

// 信号处理函数
void sig_usr(int signo)
{
    
    
    if (signo == SIGUSR1)
    {
    
    
        printf("收到了SIGUSR1信号,我休息15秒......!\n");
        sleep(15);
        printf("收到了SIGUSR1信号,我休息15秒完毕,苏醒了......!\n");
    }
    else if (signo == SIGUSR2)
    {
    
    
        printf("收到了SIGUSR2信号,我休息5秒......!\n");
        sleep(5);
        printf("收到了SIGUSR2信号,我休息5秒完毕,苏醒了......!\n");
    }
    else
    {
    
    
        printf("收到了未捕捉的信号%d!\n", signo);
    }
}

int main(int argc, char* const* argv)
{
    
    
    // 系统函数,第一个参数是个信号,第二个参数是个函数指针,代表一个针对该信号的捕捉处理函数
    if (signal(SIGUSR1, sig_usr) == SIG_ERR)
    {
    
    
        printf("无法捕捉SIGUSR1信号!\n");
    }

    if (signal(SIGUSR2, sig_usr) == SIG_ERR)
    {
    
    
        printf("无法捕捉SIGUSR2信号!\n");
    }

    for (;;)
    {
    
    
        sleep(1);
        printf("休息1秒~~~~!\n");
    }

    printf("再见!\n");

    return 0;
}

(1) 如下图所示,用 kill 发送 USR1 信号给进程,执行信号处理函数被卡住了 15 秒,这个时候因为流程回不到 main(),所以 main() 中的语句无法得到执行。

在这里插入图片描述

(2) 用 kill 发送 SIGUSR1 信号给进程,在触发 SIGUSR1 信号并因此 sleep 了 15 秒种期间,就算多次触发 SIGUSR1 信号,也不会重新执行 SIGUSR1 信号对应的信号处理函数,而是会等待上一个 SIGUSR1 信号处理函数执行完毕才第二次执行 SIGUSR1 信号处理函数。也就是说,在信号处理函数被调用时,操作系统建立的新信号屏蔽字(sigprocmask())自动包括了正在被递送的信号,因此,保证了在处理一个给定信号的时候,如果这个信号再次发生,那么它会阻塞到对前一个信号处理结束为止。

(3) 不管用 kill 发送了多少次 SIGUSR1 信号,在该信号处理函数执行期间,后续所有的 SIGUSR1 信号统统被归结为 1 1 1 次。比如当前正在执行 SIGUSR1 信号的处理程序但没有执行完毕,这个时候又发送来了 5 5 5 次 SIGUSR1 信号,那么当 SIGUSR1 信号处理程序执行完毕(解除阻塞)的时候,SIGUSR1 信号的处理程序也只会被调用 1 1 1 次,而不会分别调用 5 5 5 次 SIGUSR1 信号的处理程序。

在这里插入图片描述

(4) 执行 USR1 信号处理程序但是没执行完时,是可以继续进入到 USR2 信号处理程序里边去执行的,这个时候相当于 USR2 信号处理程序没执行完毕,USR1 信号处理程序也没执行完毕,此时再发送 USR1 和 USR2 都不会有任何响应。

(5) 既然是在执行 USR1 信号处理程序的时候来了 USR2 信号,导致又去执行了 USR2 信号处理程序,这就意味着只有 USR2 信号处理程序执行完毕,才会返回到 USR1 信号处理程序;只有 USR1 信号处理程序执行完毕了,才会最终返回到 main 函数主流程中去继续执行。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/129410599
今日推荐