什么是可重入?
关于可重入和不可重入这些概念网上可以找到很多,这里引用一下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:"