UC/OS II 临界状态管理
一:可重入与不可重入函数
可重入函数是指函数代码在运行过程中被中断,在中断返回时仍然能够恢复到原来的状态并能准确无误地执行的函数,,而不可重入函数则在运行过程中不可以被中断。简单的说如果一个外部中断改变了当前函数中的关键运行环境(变量的值,代码的执行位置),则该函数为不可重入的,否则为可重入的。
一般来说,如果某个函数的执行过程涉及直接对全局数据或公共数据进行存取,则该函数是不可重入的。
例:int i = 10;
int fun()
{
int j;
if(i==10)
i=20;
else
i = 0;
return ;
}
以上函数是不可重入的,因为在此程序中涉及对全局变量i的存取。如果要编写可重入函数,则一定不能直接在程序中修改全局数据,而应以参返回值的方式来访问全局数据。如果必须使用全局变量,则必须使用系统提供的临界状态处理办法禁止中断。
不可重入函数的移植性不好,在应用程序中,除非别无选择,一般不编写不可重入函数。可重入函数可以被一个以上的任务调用,而不必担心数据被破坏。可重入函数或者只使用局部变量,即变量保存在CPU寄存器中或堆栈中;或者使用全局变量,则要对全局变量予以保护。而在操作系统中,对全局数据的访问大量存在,因此在存取全局数据时,需要先关闭外部中断,进入临界状态。也就是说,在对全局变量进行存取时,不允许外部中断发生。
UC/OS II使用3种临界状态的处理办法以保护对全局数据的访问。
二:临界状态管理
1.临界状态管理办法
临界状态是指程序处于不可中断状态。进入临界状态的主要操作是关闭所有可以关闭的中断,而退出临界状态的主要操作是恢复到上一次进入临界状态时中断管理的状态。
在一般情况下,在调用不可重入函数之前以及在修改全局变量数据时,都需要称进入临界状态。当相应处理完成后,再返回到进入之前的原始状态。
在UC/OS II操作系统中,宏OS_ENTER_CRITIAL()用来描述进入临界状态所完成的操作,而OS_EXIT_CRITIAL()用来描述退出临界状态的办法。根深叶茂以根据CPU类型选择对应的临界状态处理办法,UC/OS II提供了3个进入和退出临界状态的办法,也就是说上面两个富士通对应三种代码,具体选择哪种代码,则由宏OS_CRITICAL_METHOD指定,该宏在OS_CPU.H中的定义如下:
#define OS_CRITICAL;_METHOD 1/2/3
(1),如果其为了,则仅仅使用简单的禁止/使能中断的汇编指令来实现宏OS_ENTER_CRITIAL()和OS_EXIT_CRITIAL()。这存在一个问题,即无论进入临界状态前中断管理方式如何,在退出临界状态时都是开中断的。
(2).如果将OS_CRITICAL_METHOD定时为2,则将中断前的状态入栈,退出临界状态时,则将数据出栈,这样可能有效地保证进入和退出临界状态时中断管理方法的一致。但这种处理办法需要出栈和入栈操作,从而占用了一定的系统时间。
(3).如果将OS_CRITICAL_METHOD定义为3,则在进入临界状态时,将CPU的状态寄存寄存器值保存到临界变量cpu_sr中。这个临界变量在所有函数中都将被分配空间,然后禁止中断。当退出临界状态时,将从该临界状态变量中恢复CPU的状态寄存器值,从而恢复到原来CPU管理中断的方式。这种处理办法效率较高,当然这要求当前处理器拥拥有状态寄存器,且状态寄存器的某一位可以被用来标识某处理器设置中断的办法。
2.ARM处理器临界状态处理办法
ARM处理器一般采用第三种临界处理办法。该临界处理办法定义如下:
#define OS_CRITICAL_METHOD 3
#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}
#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}
#endif
由上定义可知,进入临界状态时将调用OS_CPU_SR_Save()函数,返回当前CPSR寄存器的状态;退出临界状态时将调用OS_CPU_Restore()函数,并以前次OS_CPU_Save()函数调用的返回值为参数。