📜  重入函数

📅  最后修改于: 2021-05-20 07:48:39             🧑  作者: Mango

如果提供了在执行过程中中断该函数,提供中断服务程序并随后恢复较早执行的功能而不妨碍其较早操作的函数,则该函数被认为是可重入的。可重入函数用于硬件中断处理,递归等应用程序中。
该函数必须满足某些条件才能称为可重入:
1.它可能不使用全局和静态数据。尽管没有限制,但是通常不建议这样做。因为该中断可能会更改某些全局值,并且使用新数据恢复可重入函数的操作过程可能会产生不良结果。
2.不应修改自己的代码。这很重要,因为在整个代码中,函数的操作过程应保持不变。但是,如果中断例程每次使用不同的值或在中断之前和之后都使用可重入函数的本地副本,则可以允许这样做。 3.不应调用另一个不可重入函数。

线程安全和可重入功能
重入不同于线程安全,但紧密相关。函数可以是线程安全的,但仍然不能重入。例如,一个函数可以用一个互斥锁来包装(这避免了多线程环境中的问题),但是如果该函数在中断服务例程中使用,它可能会饿死等待第一次执行以释放该互斥锁。避免混淆的关键是可重入仅指一个正在执行的线程。从不存在多任务操作系统的时代开始就是一个概念。 (来源:https://en.wikipedia.org/wiki/Reentrancy_(computing))

非重入函数示例:

// A non-reentrant example 
// [The function depends on global variable i]
  
int i;
  
// Both fun1() and fun2() are not reentrant
  
// fun1() is NOT reentrant because it uses global variable i
int fun1()
{
    return i * 5;
}
  
// fun2() is NOT reentrant because it calls a non-reentrant
// function
int fun2()
{
   return fun1() * 5;
}

可重入函数示例:
在下面的代码中,fun2是一个可重入函数。如果中断暂停了它的执行并将控件转移到fun1。 fun1完成后,控件再次转移到fun2,并重新进入执行阶段。

// Both fun1() and fun2() are reentrant
int fun1(int i)
{
    return i * 5;
}
  
int fun2(int i)
{
   return fun1(i) * 5;
}