可重入函数,线程安全函数与异步信号安全函数

原文地址:https://www.jianshu.com/p/b5200248f0f5


Reentrancy、Thread-safe、Async-signal-safe
以前写C代码,多核多线程下时,要注意函数的可重入性,保证线程安全, 即多个线程同时调用到此函数,其结果是可预期的(固定输入,固定输出),全局变量的使用需要注意加锁,线程函数中写操作必须要加锁,读操作则看实际情况来定,如果能确认业务整体逻辑上能保证写和读是有严格时序的,不需要对读进行加锁(比如写只在模块最开始初始化时完成,其他地方只是使用,不会修改,则可以读取时不需要锁)。

源于《Unix系统高级编程》一书中12.6章节示例结尾点评部分提到示例函数虽然是线程安全的,但因为调用了malloc函数,不是异步信号安全(Async-signal-safe)的,不能在信号处理句柄中使用,对此很是不解,一番搜索查询,才有所明白。
示例函数如下

char * getenv(const char *name)
{
    int i, len;
    char *envbuf;
    pthread_once(&init_done, thread_init);
    pthread_mutex_lock(&env_mutex);
    envbuf = (char *)pthread_getspecific(key);
    if (envbuf == NULL) {
        envbuf = malloc(MAXSTRINGSZ);
        if (envbuf == NULL) {
            pthread_mutex_unlock(&env_mutex);
            return(NULL);
        }
        pthread_setspecific(key, envbuf);
    }
    len = strlen(name);
    for (i = 0; environ[i] != NULL; i++) {
        if ((strncmp(name, environ[i], len) == 0) &&
            (environ[i][len] ===)) {
            strncpy(envbuf, &environ[i][len+1], MAXSTRINGSZ-1);
            pthread_mutex_unlock(&env_mutex);
            return(envbuf);
        }
    }
    pthread_mutex_unlock(&env_mutex);
    return(NULL);
}
Note that although this version of getenv is thread-safe, it is not async-signal safe.
Even if we made the mutex recursive, we could not make it reentrant with respect to
signal handlers because it calls malloc, which itself is not async-signal safe.
  • 可重入,简而言之,就是多核CPU系统能够同时多次调用该函数进行处理,且每次调用函数处理是可预期的(固定输入,固定输出)。

  • 线程安全,简而言之,多个线程同时调用该函数,其处理结果总是可以预期的(固定输入,固定输出)

  • 异步信号安全与系统处理信号signal句柄机制有关系。当信号发生时,系统会打断正在进行的指令执行,跳转至信号句柄指令开始执行,由于信号发生是异步的,程序执行过程中可能被任何时候的产生信号所打断,如果信号处理函数中调用了锁操作或者全局变量写操作,很有可能产生死锁或者未知行为(因为可能出现锁还未释放的情况下,信号发生;其他线程正在在修改完全局变量后,即使有锁保护,由于信号发生不可预期,句柄函数的修改会导致对应全局变量的结果无法预期)

  • malloc函数本身是线程安全的,系统调用时存在全局的heap lock(堆内存锁,保证堆内存分配时的一致连续性),信号句柄中使用malloc函数时,有可能会发生在主程序调用malloc时,但还未结束,heap lock还未释放,被信号所中断,再次调用malloc函数,就会出现同一线程对heap lock连续两次锁,即会出现死锁 deadlock

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值