• 信号——信号处理函数和掩码


    信号:

    使用定时器发出一个信号,而系统捕捉到这个信号进行处理。
    一般是在主循环捕捉到这个信号,放入管道中,在主循环中检测到管道有内容,对其进行处理,这样成为统一事件源。

    问题在于:

    如果一个信号多次注册,是以最后一次注册的为准?
    我可不可以理解为这个和epoll一样,内核持有一张表,表上对应信号有不同的处理函数,如果设置了新的处理函数,就把旧的处理函数覆盖调?

    实验:

    信号处理函数覆盖实验
    test_signal.cpp

    结论

    1. 以最后一个注册为准
    2. 信号集的作用是执行信号处理函数时候的信号屏蔽字:

    测试:信号集的作用是执行信号处理函数时候的信号屏蔽字

    • 正确
    • 不过注意的是,在信号处理函数中不应该反复的设置新的信号,不然会信号堆积。
      例如:下边这种情况会导致死循环
      原因,每次调用信号处理函数都会设置一个alarm信号,而且信号处理函数的处理时间高于这个信号,就会导致信号被暂时挂起,当信号处理函数结束之后,之前挂起的SIGALARM信号会重新调用信号处理函数,所以导致while会在某个时刻卡住,不会向下执行,而是一直执行信号处理函数。
    int res = 2;
        void signal_hander2(int sig){
        int save_error = errno;
        cout << "hander2, res = " << res << endl;
        --res;
       
        alarm(1);
        sleep(2);
        cout << " end " << endl;
        errno = save_error;
    }
    int main(){
        .....
        while(res >= 0){
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试程序:

    //信号处理函数覆盖实验
    #include "signal.h"
    #include 
    #include "iostream"
    #include "string.h"
    #include "errno.h"
    using namespace std;
    int res = 2;
    void signal_hander1(int sig){
        int save_error = errno;
        cout << "hander1" << endl;
        --res;
        alarm(1);
        errno = save_error;
    }
    void signal_hander2(int sig){
        int save_error = errno;
        cout << "hander2, res = " << res << endl;
        --res;
        //if(res >= 0)
            alarm(1);
        sleep(2);
        cout << " end " << endl;
        errno = save_error;
    }
    void addsig(int sig, void (*hander)(int)){
        struct sigaction act;
        memset(&act, '\0', sizeof(act));
        act.sa_handler = *hander;
        act.sa_flags |= SA_RESTART;
        sigfillset(&act.sa_mask);
        sigaction(sig, &act, NULL);
    }
    
    int main(){
        alarm(1);
        sigset_t newmask;
        
        //addsig(SIGALRM, signal_hander1);
        addsig(SIGALRM, signal_hander2);
        
        while(res >= 0){
            //cout << "!" << endl;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    解决方法:

    • 不要把alarm放在信号处理函数中,可以使用统一信号源,放在主循环中处理。
    • 或者在信号处理函数中增加一层判断,判断是否要继续调用alarm
  • 相关阅读:
    广告道闸有哪些类型,停车场广告道闸安装实施流程是怎么样的
    代码讲解 Java注解详解和自定义注解实战
    c语言 编程及答案
    全都会!预测蛋白质标注!创建讲义!解释数学公式!最懂科学的智能NLP模型Galactica尝鲜 ⛵
    IDEA中的properties文件中文乱码
    服务器操作系统到底用win还是linux好?
    2023中国(深圳)国际设备维护、状态监测及故障诊断维修展览会
    java计算机毕业设计ssm养老管理系统-敬老院系统
    tf.compat.v1.estimator.tpu.TPUEstimator参数说明
    Si3262 一款低功耗刷卡+触摸+mcu 三合一SOC芯片
  • 原文地址:https://blog.csdn.net/qq_42370809/article/details/126102966