私信TA

用户名:chenqi

访问量:37161

签 名:

等  级
排  名 321
经  验 5453
参赛次数 0
文章发表 52
年  龄 0
在职情况 学生
学  校
专  业

  自我简介:

TA的其他文章

可重入函数与不可重入函数

在多任务系统当中,在任务执行期间捕捉到信号并对其进行处理时,进程正在执行的指令序列就被信号处理程序临时中断。如果从信号处理程序返回,则继续执行进程断点处的正常指令序列,从重新恢复到断点重新执行的过程中,函数所依赖的环境没有发生改变,就说这个函数是可重入的,反之就是不可重入的。
    进程中断期间,系统会保存和恢复进程的上下文,然而仅限于返回地址,cpu寄存器等之类的少量上下文,函数内部使用的诸如全局或静态变量,buffer等并不在保护之列,所以如果这些值在函数被中断期间发生了改变,那么当函数回到断点继续执行时,其结果就不可预料了。

例子1:

一个进程正在执行malloc分配堆空间,此时程序捕捉到信号发生中断,执行信号处理程序中恰好也有一个malloc,这样就会对进程的环境造成破坏,因为malloc通常为它所分配的存储区维护一个链接表,插入执行信号处理函数时,进程可能正在对这张表进行操作,而信号处理函数的调用刚好覆盖了进程的操作,造成错误。

例子2:

    一般浮点运算都是由专门的硬件来完成,假设有个硬件寄存器名字叫做FLOAT,用来计算和存放浮点数的中间运算结果。

void fun()

{

//...这个函数对FLOAT寄存器进行操作

}

    假如第一次执行,有个对浮点数操作运算的结果临时存在FLOAT寄存器中,而就在这时被中断了,而中断函数或者另一个进程也调用fun函数,这时第二次调用的fun函数在执行的过程中就会破坏第一次FLOAT寄存器中的结果,这样当返回到第一次fun函数的时候,结果就不正确了。

满足下面条件之一的多数是不可重入函数:
(1)使用了静态数据结构;
(2)调用了malloc或free;
(3)调用了标准I/O函数;标准io库很多实现都以不可重入的方式使用全局数据结构。

(4)进行了浮点运算.许多的处理器/编译器中,浮点一般都是不可重入的 (浮点运算大多使用协处理器或者软件模拟来实现。

常见的不可重入函数有:
printf --------引用全局变量

malloc --------全局内存分配表
free--------全局内存分配表

避免不可重入函数的设计原则

不要使用全局变量。因为别的代码很可能覆盖这些变量值。

和硬件发生交互的时候,切记关闭硬件中断,完成交互记得打开中断。

不能调用其它任何不可重入的函数。

谨慎使用堆栈,堆栈操作涉及内存分配,稍不留神就会造成溢出导致覆盖其他任务的数据。

例子3:
  unsigned int sum_int( unsigned int base )

{
     unsigned int index;
    static unsigned int sum = 0; // 注意,是static类型
    for (index = 1; index <= base; index++)

{
     sum += index;
     return sum;
   }

分析:这个函数之所以是不可预测的,就是因为函数中使用了static变量,因为static变量的特征,这样的函数被称为:带“内部存储器”功能的的函数。将上面的函数修改为可重入的函数,只要将声明sum变量中的static关键字去掉,变量sum即变为一个auto类型的变量,函数即变为一个可重入的函数。当然,有些时候,在函数中是必须要使用static变量的,比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。


注:网上资料参考

 

0.0分

0 人评分

  评论区

  • «
  • »