1非重入函数在实时系统的设计中,多个任务通常调用同一函数。
如果不幸的是有一个这样设计的函数:当不同的任务调用此函数时,它可能会修改其他调用此函数的任务的数据,从而导致不可预期的后果。
这样的函数是不安全的函数,也称为非可重入函数。
2可重入函数必须有一个安全函数,该安全函数也称为可重入函数。
那么什么是可重入函数?所谓的可重入是指可以由多个任务调用的进程,并且该任务不必担心数据在被调用时是否会出错。
可重入函数只是可以中断的函数,也就是说,可以在执行此函数期间随时将其中断,可以将其转移到OS计划中以执行另一段代码,并且返回时不会发生任何错误。
控制 ;非可重入函数使用某些系统资源,例如全局变量区域,中断向量表等,因此,如果它们被中断,则可能会出现问题。
此类功能无法在多任务环境中运行。
还可以理解,重新进入意味着重复进入。
首先,这意味着可以中断此功能。
其次,这意味着除了在自己的堆栈上使用变量外,它不依赖于任何环境(包括静态)。
这样的函数是purecode(纯代码)是可重入的,允许运行该函数的多个副本,并且由于它们使用单独的堆栈,因此它们不会互相干扰。
如果确实需要访问全局变量(包括静态变量),则必须注意实现互斥。
可重入函数在并行运行时环境中非常重要,但是它们通常必须为访问全局变量付出一些性能成本。
编写可重入函数时,如果使用全局变量,则应通过关闭中断和信号灯(即P,V操作)的方式来保护它们。
注意:如果使用的全局变量未受保护,则该函数将不可重入,即,当多个进程调用此函数时,相关的全局变量很有可能变得不可知。
示例:假设Exam是一个int类型的全局变量,则函数Squre_Exam返回Exam的平方值。
然后,以下函数将不可重入。
int Exam = 0; unsigned int example(int para){unsigned int temp;考试=段落; //(**)temp = Square_Exam(); return temp;}如果该函数被多个进程调用,则结果可能是未知的,因为当刚执行(**)语句时,可能仅激活使用该函数的另一个进程,然后在新激活的进程执行时此函数将使Exam分配一个不同的para值,因此当控件返回“ temp = Square_Exam()”时,计算出的温度可能不是预期的结果。
此功能应改进如下。
int Exam = 0; unsigned int example(int para){unsigned int temp; [适用于信号量操作] //(1)Lock Exam = para; temp = Square_Exam(); [释放信号量操作] //解锁返回温度;}无法申请“信号量”,表明另一个进程正在分配考试并计算其平方(即,正在使用此信号),并且该过程必须等待其信号被释放,然后才能继续执行。
如果请求了信号,它可以继续执行,但是其他进程必须等待该进程释放信号量,然后才能再次使用该信号。
3确保函数可重入性的判断条件:1)编写函数时,尝试使用局部变量(例如寄存器,堆栈中的变量); 2)保护要使用的全局变量(例如关闭中断,相互排斥的方法,例如信号量),这样构成的函数必须是可重入函数。
满足以下条件的大多数函数都是不可重入的(不安全的):1)函数主体中使用了静态数据结构; 2)在函数体中调用Malloc()或free()函数; 3)在功能主体/ O功能中调用标准I。
如何将非可重入函数重写为可重入函数?使非可重入函数重入的唯一方法是使用可重入规则重写它。
实际上非常简单。
只要遵循一些易于理解的规则,您编写的函数就可以重入:1)不要使用全局变量。
因为其他代码很可能会更改这些变量的值。
2)与硬件进行交互时,请记住执行诸如disinterrupt()之类的操作,以关闭硬件中断。
完成交互后,请记住打开中断。
在某些系列中,这被称为“进入/退出核心”。
3)不能调用其他非重入函数。
4)使用