可重入函数
可重入函数(reentrant):在任意时刻可以被中断,稍后再继续运行,不会丢失数据,即不用担心数据被其他线程篡改。可重入函数必须满足以下三个条件:
- 可以在执行的过程中可以被打断;
- 被打断之后,在该函数一次调用执行完之前,可以再次被调用(或进入,reentered)。
- 再次调用执行完之后,被打断的上次调用可以继续恢复执行,并正确执行。
不可重入函数
多任务调用某一不可重入函数时,可能修改其他任务调用该函数的数据,从而导致不可预料的后果。
即不可重入函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。
满足下面条件之一的都数是不可重入函数:
- 使用了静态数据结构或者全局变量;
- 调用了malloc或free;
- 调用了标准I/O函数;标准io库很多实现都以不可重入的方式使用全局数据结构。
- 进行了浮点运算.许多的处理器/编译器中,浮点一般都是不可重入的 (浮点运算大多使用协处理器或者软件模拟来实现。
- 调用printf。( 注:printf引用全局stdout; malloc, free会引用全局的内存分配表。)
如何保证可重入
-
不要使用全局变量和static变量。因为别的代码很可能改变这些变量值。
-
在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量);
-
对于要使用的全局变量要加以保护(如采取关中断、信号量等互斥方法),这样构成的函数就一定是一个可重入的函数。
-
不能调用其它任何不可重入的函数。,printf都是不可重入的.
---->存疑:信号的处理函数要求是可重入的?—.我确实可以在里面写个printf啊 -
谨慎使用堆栈。
-
在和硬件发生交互的时候,切记执行类似 disinterrupt() 之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/ 退出核心”。
可重入与线程安全
- 可重入函数与线程安全没有必然联系。
- 即,一个可重入函数不一定是线程安全的,一个线程安全的函数不一定是可重入的。比如printf,是线程安全的,但是却不可重入。
- 但,不可重入函数一定不是线程安全的。