如上图所示链表,在插入节点的时候捕获到了信号,并且该信号的自定义处理方式中也调用了插入节点的函数。
在main函数中,使用insert向链表中插入一个节点node1,在执行insert的时,刚让头节点指向node1以后(如上图序号1),捕获到了信号,进入到了该信号的自定义处理方式中。
在自定义处理方式中,同样调用了insert函数向链表中插入一个节点node2,此时完整的执行了insert函数,但是在头节点和最开始那个节点之间同时有了node1和node2(如上图序号2和3)。
当第二次调用insert中让头节点指向node2后(如上图序号3),流程返回到信号的自定义处理函数中,然后再返回到第一次调用insert处,头节点指向node1(如上图序号4)。
最后可以看到,该链表是丢了一个节点的。
重入:像insert函数这样,在main流程中调用还没有返回时就再次被handler流程调用再次进入该函数。
nsert函数访问的是一个全局链表,有可能会因为重入和造成错乱,像insert这样的函数就称为不可重入函数。
如果一个函数只访问自己的局部变量或参数,则不会造成错乱,此时这样的函数就称为可重入函数。
注意: 可/不可重入是函数的特性,是中性的,并不是问题,所以也不需要被解决。
我们目前使用的大部分结构都是不可以重入函数!!!。
符合以下条件之一的就是不可重入函数:
调用了malloc或者free,因为malloc也是用全局链表来管理堆的。
调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构。