可重入与不可重入 2007年08月26日 星期日 15:20 一:可重入函数 在实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果。那么什么是可重入函数呢? 所谓可重入函数是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。不可重入函数在实时系统设计中被视为不安全函数。 满足下列条件的函数多数是不可重入的: (1)函数体内使用了静态的数据结构; (2)函数体内调用了malloc()或者free()函数; (3)函数体内调用了标准I/O函数。 下面举例加以说明。 可重入函数 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; // 使用了静态局部变量,在分享内存的多个线程中可能造成问题 } 如何写出可重入的函数?在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。:) 二: 一、可重入函数 1)什么是可重入性? 可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反, 不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。 2)可重入函数: 不为连续的调用持有静态数据。 不返回指向静态数据的指针;所有数据都由函数的调用者提供。 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。 如果必须访问全局变量,记住利用互斥信号量来保护全局变量。 绝不调用任何不可重入函数。 3)不可重入函数: 函数中使用了静态变量,无论是全局静态变量还是局部静态变量。 函数返回静态变量。 函数中调用了不可重入函数。 函数体内使用了静态的数据结构; 函数体内调用了malloc()或者free()函数; 函数体内调用了其他标准I/O函数。 函数是singleton中的成员函数而且使用了不使用线程独立存储的成员变量 。 总的来说,如果一个函数在重入条件下使用了未受保护的共享的资源,那么它是不可重入的。