可重入、线程安全和异步信号安全

本文介绍了可重入的概念,强调无状态的函数是可重入的,而像malloc、使用静态数据结构或标准I/O库的函数则可能不可重入。可重入和线程安全不同,线程安全关注多线程环境下的函数调用,而可重入适用于单线程或多线程。此外,可重入函数通常是异步信号安全的,但反之不成立。文章给出了编写可重入函数的最佳实践,如避免使用静态数据和全局变量,以及注意内存分配和释放的函数。
摘要由CSDN通过智能技术生成

什么是可重入?

​   关于可重入和不可重入这些概念网上可以找到很多,这里引用一下WiKi中的解释

a computer program or subroutine is called reentrant if it can be interrupted in the middle of its execution, and then be safely called again (“re-entered”) before its previous invocations complete execution. The interruption could be caused by an internal action such as a jump or call, or by an external action such as an interrupt or signal. Once the reentered invocation completes, the previous invocations will resume correct execution.

​   简单来说是这样的,可重入指的是一个程序或者函数所具备的性质,该性质指的是一个函数在执行的过程中被中断,程序的执行流跑到另外的一个地方把这个函数重新执行了一次,执行完成后返回被中断的地方再次运行之前的函数,而这个整个过程不会影响这个被打断的函数的最终结果,那么就称这个函数是可重入的。举一个可重入函数的例子,比如计算两个值的大小,用户传入两个值,通过加法进行计算,最后返回结果,即使这个函数被中断并被再次运行,也不会影响这个函数的最终结果,因为这个函数是无状态的,如果一个函数在执行的过程中需要把计算的中间结果保存起来,那么这就不是可重入的了,比方说,gethostbyname这个函数在解析域名对应的ip地址的时会将计算的结果放在一个静态的存储中返回,如果某一个时刻调用gethostbyname,将域名已经解析好对应的ip地址了,然后放在静态存储中,在准备返回的时候被中断了,然后再次执行这个函数,但是解析的是另外一个域名,解析后的结果依然会放到静态存储中,那么这次调用就会把之前解析出来的结果给覆盖掉,本质原因就是因为这个函数是有状态的,无状态的函数一定是可重入的。

​   相信通过上面的简单介绍你或许对可重入和不可重入有了一丁丁了解,常见的不可重入的函数一般都具备以下特征:

  • 调用malloc或free (malloc内部维护了全局的链表用来管理分配的内存,这就是状态信息,free也一样)
  • 使用了静态数据结构(全局变量或静态变量)
  • 标准I/O程序库的一部分(内部会有全局锁,锁也是一种状态)
  • 调用了一个不可重入的函数

下面举一个不可重入函数的两个小例子:

#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;
struct data
{
        int a;
        int b;
}da;

void handler(int signum)
{
        cout << "data:"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值