可重入函数与不可重入函数

  • Post author:
  • Post category:其他


一:概念

(1)所谓的可重入函数:就是我们在信号处理函数中 调用它 是安全的;可重入函数,即在信号处理程序中保证调用安全的函数,这些函数是可重入的并被称为异步信号安全的;比如,malloc就是一个不可重入函数,当我们在主函数当中调用它时,如果,它还没处理结束(和内部的实现有关),这个时候,又来了一个信号,而我们又在信号处理函数当中去调用malloc,这个时候,由于malloc自己内部实现的原因,可能要用到某个全局变量等,由于在主函数当中还没结束调用,所以,就会在信号处理函数当中出现异常的情况。

处理信号程序流程:

在这里插入图片描述

二:不可重入函数使用建议

//在写信号处理函数的时候,要注意的事项:

(a)在信号处理函数中,尽量使用简单的语句做简单的事情,尽量不要调用系统函数以免引起麻烦;

(b)如果必须要在信号处理函数中调用一些系统函数,那么要保证在信号处理函数中调用的 系统函数一定要是可重入的;

©如果必须要在信号处理函数中调用那些可能修改errno值的可重入的系统函数,那么 就得事先备份errno值,从信号处理函数返回之前,将errno值恢复;

例如:

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

//信号处理函数
void sig_usr(int signo)
{     
    //先保存errno的值,
    int myerrno = errno;

    if(signo == SIGUSR1)
    {
        printf("收到了SIGUSR1信号!\n");
    }
    else if(signo == SIGUSR2)
    {
        printf("收到了SIGUSR2信号!\n");
    }
    else
    {
        printf("收到了未捕捉的信号%d!\n",signo);
    }
    
    //最后进行恢复
    errno = myerrno;
}

int main(int argc, char *const *argv)
{
    if(signal(SIGUSR1,sig_usr) == SIG_ERR)  //系统函数,参数1:是个信号,参数2:是个函数指针,代表一个针对该信号的捕捉处理函数
    {
        printf("无法捕捉SIGUSR1信号!\n");
    }
    if(signal(SIGUSR2,sig_usr) == SIG_ERR) 
    {
        printf("无法捕捉SIGUSR2信号!\n");
    }
    for(;;)
    {
        sleep(1); //休息1秒
        printf("休息1秒\n");        
    }
    printf("再见!\n");
    return 0;
}

三:不可重入函数范例演示

范例一:



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

int g_mysign = 0;
//我这个函数能够修改这个全局变量g_mysign的值
void muNEfunc(int value) 
{
    //.....其他处理代码
    g_mysign = value;  
    //.....其他处理代码
}

//信号处理函数
void sig_usr(int signo)
{     

    muNEfunc(22); //因为一些实际需求必须要在sig_user这个信号处理函数里调用muNEfunc

    int myerrno = errno;

    if(signo == SIGUSR1)
    {
        printf("收到了SIGUSR1信号!\n");
    }
    else if(signo == SIGUSR2)
    {
        printf("收到了SIGUSR2信号!\n");
    }
    else
    {
        printf("收到了未捕捉的信号%d!\n",signo);
    }
}

int main(int argc, char *const *argv)
{
    if(signal(SIGUSR1,sig_usr) == SIG_ERR)  //系统函数,参数1:是个信号,参数2:是个函数指针,代表一个针对该信号的捕捉处理函数
    {
        printf("无法捕捉SIGUSR1信号!\n");
    }
    if(signal(SIGUSR2,sig_usr) == SIG_ERR) 
    {
        printf("无法捕捉SIGUSR2信号!\n");
    }
    for(;;)
    {
        sleep(1); //休息1秒
        printf("休息1秒\n");        
        
        /*我们希望在调用muNEfunc函数以后,得到g_mysign的值为15,
        但是,如果在执行完muNEfunc函数以后,突然来了一个信号,这时
        程序执行流程到了信号处理函数当中,而信号处理函数又对muNEfunc
        当中的g_mysign变量的值做出了改变,所以,当信号处理函数执行完毕以后
        再次回到主函数当中时,g_mysign的值便不是我们所希望的了*/
        muNEfunc(15);
        printf("g_mysign=%d\n",g_mysign); 
        //拿g_mysign做一些其他用途;
    }
    printf("再见!\n");
    return 0;
}

范例二:

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

//信号处理函数
void sig_usr(int signo)
{   
    //这里也malloc,这是错用,不可重入函数不能用在信号处理函数中;
    int* p;
    p = (int *) malloc (sizeof(int)); //用了不可重入函数;
    free(p);

    if(signo == SIGUSR1)
    {
        printf("收到了SIGUSR1信号!\n");
    }
    else if(signo == SIGUSR2)
    {
        printf("收到了SIGUSR2信号!\n");
    }
    else
    {
        printf("收到了未捕捉的信号%d!\n",signo);
    }
    
}

int main(int argc, char *const *argv)
{
    /*系统函数,参数1:是个信号,参数2:是个函数指针,代表一个针对该信号的捕捉处理函数*/
    if(signal(SIGUSR1,sig_usr) == SIG_ERR)  
    {
        printf("无法捕捉SIGUSR1信号!\n");
    }
    if(signal(SIGUSR2,sig_usr) == SIG_ERR) 
    {
        printf("无法捕捉SIGUSR2信号!\n");
    }
    for(;;)
    {             
        int* p;
        p = (int *) malloc (sizeof(int));
        free(p);
    }
    printf("再见!\n");
    return 0;
}

在信号处理函数当中调用了,不不可重入函数以后,发现后面就收不到SIGUSER1信号了.

在这里插入图片描述



版权声明:本文为qq_38158479原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。