嵌入式实时系统设计中,经常碰到多个任务调用同一个函数的情况。如果此函数当初不幸被设计成不可重入函数的话,那么不同任务调用该函数时可能修改其他任务调用该函数的数据,从而导致不可预料的后果。
那么什么是可重入函数呢?所谓可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。不可重入函数在实时系统设计中被视为不安全函数。
满足下列条件的函数多数是不可重入的:
(1)函数体内使用了静态的数据结构;
(2)函数体内调用了malloc()或者free()函数;
(3)函数体内调用了标准I/O函数;
如何写出可重入的函数?在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用缺省态(auto)局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号来保护全局变量,或者调用该函数前关中断,调用后再开中断。
可重入函数可以被一个以上的任务调用,而不必担心数据被破坏。可重入函数任何时候都可以被中断,一段时间以后又可以运行,而相应的数据不会丢失。可重入函数或者只使用局部变量,即保存在CPU寄存器中或堆栈中;或者使用全局变量,则要对全局变量予以保护。
写可重入函数应遵守的规则:
Rule 1、不要使用全局变量。因为别的代码很可能覆盖这些变量值。
Rule2、在和硬件交互时,谨记执行类似disinterrupt()之类的操作,即为关闭硬件中断。交互结束切记打开中断,在某些系列上,这叫做“进入/退出核心”或者用OS_ENTER_KERNAL/OS_EXIT_KERNAL来描述。/*这是临界区保护*/
Rule3、不能调用任何不可重入的函数。
Rule4、谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL。
总之,在灵魂深处时刻呼唤:保证中断是安全的!!!!!
中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展——让标准C支持中断。具体代表事实即产生了一个新的关键字__interrupt关键字去定义了一个中断服务子程序(ISR),请评论以下代码段:
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf(“\nArea = %f”, area);
return area;
}
该函数就是为面试而生的啊,错误很多:
1)ISR不能返回一个值。如果你不懂这个,洗洗睡吧,好有精神找下一家。
2)ISR不能传递参数。如果你没有看到这一点,结果参考第一点。
3)在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需 要让额外的寄存器入栈,有些处理器/编译器就不允许在ISR中做浮点运算。此 外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智,不可取的。
4)与第三点一脉相承,printf()经常有重入和性能上的问题。
/**********************************************************************************************//在系统运行过程中,一定是某种中断源发出了相应的中断,系统上挂接的中断服
//务程序进行现场的处理,例如告警等操作,然后清中断。即中断服务程序连接在
//某一类中断源上,而这些中断源的产生是随机的,所以中断服务程序并没有一个
//固定的调用者,也没有固定的返回地址,故返回值也没有用。以下举例说明可重
//入函数 && 不可重入函数。
/**********************************************************************************************
//可重入函数
void strcpy(char* lpszDest, char* lpszSrc)
{
while(*lpszDest++ = *lpszSrc++);
*dest = 0;
}
//不可重入函数1
char cTemp; //全局变量
void SwapChar1(char* lpcX, char* lpcY)
{
cTemp = *lpcX;
*lpcX = *lpcY;
*lpcY = cTemp; //访问了全局变量,在分享内存的多个线程中可能造成问题
}
//非可重入函数2
void SwapChar2(char* lpcX, char*lpcY)
{
static char cTemp; //静态局部变量
cTemp = *lpcX;
*lpcX= *lpcY;
*lpcY = cTemp; //使用静态局部变量,在分享内存多个线程中可能造成问题
}
最后问一遍如何写出可重入的函数?在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。