在多任务环境下编程与在裸机环境下编程有很多不一样的地方,函数的可重入性就是其中一个需要注意的细节。什么是函数的可重入性呢,我们先从一个实例开始介绍。
//不可重入函数示例
int sum(int len){
static int sum = 0;
for(int i=0; i<len; i++)
sum += i;
return sum;
}
void tast1(void){
sum(2);
}
void task2(void){
sum(4);
}
假设在一个多任务环境中,定义了一个sum()函数用来对累加求和。sum()函数首先被任务task1调用,在sum()函数运行期间,任务task1被调度器挂起,CPU切换到task2运行,sum()函数被任务task2再次调用。由于sum()函数内定义的有静态变量,当在运行期间被打断后再次被调用,就有可能影响sum()函数在task1和task2中的运行结果
在一个多任务环境中,一个函数如果可以被多次重复调用,或者被多个任务并发调用,函数在运行过程中可以随时随地被打断,并不影响该函数的运行结果,我们称这样的函数为可重入函数。相反,如果一个函数不能多次并发调用,在执行过程中不能被中断,否则就会影响函数的运行结果,那么这个函数就是不可重入函数,如上面的sum()函数。
在裸机环境下面,我们不需要考虑函数的可重入问题,因为裸机环境下只有一个主程序main()一直在独占CPU运行。但是在多任务环境下,如果该函数可能被多次调用,或者在执行过程中可能会被中断或被任务调度器打断,此时我们就要考虑该函数的可重入问题了
| 不可重入函数 | 可重入函数 |
|---|---|
| 函数内部使用了全局变量或静态局部变量 | 函数内部不能使用全局变量或静态局部变量 |
| 函数返回值是一个全局变量或静态变量 | 函数返回值不能是全局变量或静态变量 |
| 函数内部调用了malloc()/free()函数 | 不适用标准I/O函数 |
| 函数内部使用了标准I/O函数 | 不适用malloc()/free()函数 |
| 函数内部调用了其他不可重入函数 | 不调用不可重入函数 |