可重入函数
2015-09-16 14:50
232 查看
可重入函数
当捕捉到信号时,不论进程的主控制流程当前执行到哪儿,都会先跳到信号处理函数中执行,从信号处理函数返回后再继续执行主控制流程。信号处理函数是一个单独的控制流程,因为它和主控制流程是异步的,二者不存在调用和被调用的关系,并且使用不同的堆栈空间。引入了信号处理函数使得一个进程具有多个控制流程,如果这些控制流程访问相同的全局资源(全局变量、硬件资源等),就有可能出现冲突,如下面的例子所示。图 33.3. 不可重入函数
main函数调用
insert函数向一个链表
head中插入节点
node1,插入操作分为两步,刚做完第一步的时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换到
sighandler函数,
sighandler也调用
insert函数向同一个链表
head中插入节点
node2,插入操作的两步都做完之后从
sighandler返回内核态,再次回到用户态就从
main函数调用的
insert函数中继续往下执行,先前做第一步之后被打断,现在继续做完第二步。结果是,
main函数和
sighandler先后向链表中插入两个节点,而最后只有一个节点真正插入链表中了。
像上例这样,
insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,
insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为不可重入函数,反之,如果一个函数只访问自己的局部变量或参数,则称为可重入(
Reentrant)函数。想一下,为什么两个不同的控制流程调用同一个函数,访问它的同一个局部变量或参数就不会造成错乱?
如果一个函数符合以下条件之一则是不可重入的:
调用了
malloc或
free,因为
malloc也是用全局链表来管理堆的。
调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构。
相关文章推荐