美文网首页
可重入函数

可重入函数

作者: 夏至亦韵 | 来源:发表于2017-07-18 18:01 被阅读0次

    ## 可重入函数

    ### 可重入性的理解

    若一个程序或子程序可以安全的被并行执行,则称其为可重入的;即当该子程序正在运行时,可以再次进入并执行它。若一个函数是可重入的,则该函数必须满足一下必要条件:

    1. 不能含有静态(全局)非常量数据。

    2. 不能返回静态(全局)非常量数据的地址。

    3. 只能处理由调用者提供的数据。作为可重入函数的输入参数,只能由调用者提供,而且所提供的输入数据必须满足上面两点要求

    4. 不能依赖于单实例模式资源的锁。

    5. 不能调用不可重入的函数。

    6. 函数内部,尽量不能用 malloc 和 free 之类的方法进行内存分配和释放,如果使用,一般情况下会造成该函数的不可重入.

    可重入函数主要用于多任务环境中。可重入的函数必须满足以下三个条件:

    (1)可以在执行的过程中可以被打断;

    (2)被打断之后,在该函数一次调用执行完之前,可以再次被调用(或进入,reentered)。

    (3)再次调用执行完之后,被打断的上次调用可以继续恢复执行,并正确执行。

    ### 不可重入函数的示例

    如果一个函数只有调用者提供的非静态变量参数,并且函数中只依赖自己栈上的环境,也没有调用其他的不可重入函数,那么他就一定是可重入的.这样的函数就是purecode(纯代码)可重入,可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以不会互相干扰。如果确实需要访问全局变量(包括 static),一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要,但是一般要为访问全局变量付出一些性能代价。

    编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。

    说明:若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态。

    ```cpp

    int Exam = 0;

    unsigned int example( int para )

    {

    unsigned int temp;

    Exam = para; // (**)

    temp = Square_Exam( );

    return temp;

    }

    ```

    此函数若被多个进程调用的话,其结果可能是未知的,因为当(**)语句刚执行完后,另外一个使用本函数的进程可能正好被激活,那么当新激活的进程执行到此函数时,将使 Exam 赋与另一个不同的 para 值,所以当控制重新回到 “temp = Square_Exam( )” 后,计算出的temp很可能不是预想中的结果。此函数应如下改进。

    ```cpp

    view plaincopy在CODE上查看代码片派生到我的代码片

    int Exam = 0;

    unsigned int example( int para )

    {

    unsigned int temp;

    [申请信号量操作] //(1)  加锁

    Exam = para;

    temp = Square_Exam( );

    [释放信号量操作] //    解锁

    return temp;

    }

    ```

    申请不到“信号量”,说明另外的进程正处于给 Exam赋值并计算其平方过程中(即正在使用此信号),本进程必须等待其释放信号后,才可继续执行。若申请到信号,则可继续执行,但其它进程必须等待本进程释放信号量后,才能再使用本信号。

    保证函数的可重入性的方法:

    1. 在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量);

    2. 对于要使用的全局变量要加以保护(如采取关中断、信号量等互斥方法),这样构成的函数就一定是一个可重入的函数。

    满足下列条件的函数多数是不可重入(不安全)的:

    1. 函数体内使用了静态的数据结构;

    2. 函数体内调用了malloc() 或者 free() 函数;

    3. 函数体内调用了标准 I/O 函数。

    相关文章

      网友评论

          本文标题:可重入函数

          本文链接:https://www.haomeiwen.com/subject/lgoalttx.html