重入函数

可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。

怎么会有可重入和不可重入的概念呢?在多任务系统下,中断可能在任务执行的任何时间发生;如果一个函数的执行期间被中断后,到重新恢复到断点进行执行的过程中,函数所依赖的环境没有发生改变,那么这个函数就是可重入的,否则就不可重入。在中断前后不都要保存和恢复上下文吗,怎么会出现函数所依赖的环境发生改变了呢?我们知道中断时确实保存一些上下文,但是仅限于返回地址,cpu寄存器等之类的少量上下文,而函数内部使用的诸如全局或静态变量,buffer等并不在保护之列,所以如果这些值在函数被中断期间发生了改变,那么当函数回到断点继续执行时,其结果就不可预料了。

满足下面条件之一的多数是不可重入函数:

(1)使用了静态数据结构;

比如使用或者返回全局变量,静态局部变量

(2)调用了malloc或free;

malloc/free是不可重入的,它们使用了全局变量来指向空闲区。malloc通常会为所分配的存储区维护一个链接表,而插入执行信号处理函数的时候,进程可能正在修改此链接表;

(3)调用了标准I/O函数;

标准I/O库的很多实现都使用了全局数据结构;

(4)进行了浮点运算.

许多的处理器/编译器中,浮点一般都是不可重入的

(浮点运算大多使用协处理器或者软件模拟来实现)。举个例子假设有个硬件寄存器名字叫做FLOAT,用来计算和存放浮点数的中间运算结果假设有这么个函数

void fun()

{

//...

}

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

在信号处理程序及多线程编程时,要特别注意。考虑这种情况:

1) 信号处理程序A内外都调用了同一个不可重入函数B;B在执行期间被信号打断,进入A

(A中调用了B),完事之后返回B被中断点继续执行,这时B函数的环境可能改变,其结果就不可预料了。

2)

多线程共享进程内部的资源,如果两个线程A,B调用同一个不可重入函数F,A线程进入F后,线程调度,切换到B,B也执行了F,那么当再次切换到线程A时,其调用F的结果也是不可预料的。

在信号处理程序中即使调用可重入函数也有问题要注意。作为一个通用的规则,当在信号处理程序中调用可重入函数时,应当在其前保存errno,并在其后恢复errno。(要了解经常被捕捉到的信号是SIGCHLD,其信号处理程序通常要调用一种wait函数,而各种wait函数都能改变errno。)可重入函数在多线程条件下,函数应当是线程安全的,进一步,更强的条件是可重入的。一个可重入函数保证了在多线程条件下,函数的状态不会出现错误。eg.

in cstatic int tmp;

void swap1(int* x, int* y)

{

tmp=*x;

*x=*y;

*y=tmp;

}

void swap2(int* x, int* y)

{

int

tmp;

tmp=*x;

*x=*y;

*y=tmp;

}

swap1是不可重入的,swap是可重入的。因为在多线程条件下,操作系统会在swap1还没有执行完的情况下,切换到另一个线程中,那个线程可能再次调用swap1,这样状态就错了。

一个函数如果满足以及下条件之一,那么它是不可重入的:

函数中使用了静态变量,无论是全局静态变量还是局部静态变量。

函数返回静态变量。

函数中调用了不可重入函数。

函数是singleton中的成员函数而且使用了不使用线程独立存储的成员变量

总的来说,如果一个函数在重入条件下使用了未受保护的共享的资源,那么它是不可重入的。

什么是可重入性?可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反,

不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。

可重入函数:不为连续的调用持有静态数据。不返回指向静态数据的指针;所有数据都由函数的调用者提供。使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。绝不调用任何不可重入函数。

编写可重入函数原则:

1、不要使用静态数据结构,坚持只用局部变量;

2、若必须访问全局变量,利用互斥信号量来保护全局变量;

3、获取得知哪些系统调用是可重入的,在多任务处理程序中都使用安全的系统调用;

4、不调用其它任何不可重入的函数;

5、谨慎使用堆栈。堆栈操作涉及内存分配,稍不留神就会造成益出导致覆盖其他任务的数据,最好先在使用前先OS_ENTER_KERNAL;

6、在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”。

Java重入函数_重入函数相关推荐

  1. java 虚基类_重拾C++之虚函数和虚基类以及抽象类

    一.引言 好久没接触过C++了,今天突然要用一点感觉号蛋疼,用惯了python感觉C++一点都不会了. 声明了一个类的对象居然用这种方法,脑子绝对是被驴(python)踢了 class A{ ... ...

  2. java内联函数_Java之内联函数_内联函数的优缺点

    描述 内联函数 1.内联函数就是指函数在被调用的地方直接展开,编译器在调用时不用像一般函数那样,参数压栈,返回时参数出栈以及资源释放等,这样提高了程序执行速度. 2.Java语言中有一个关键字fina ...

  3. java定义类模板_定义模板——函数模板和类模板

    面向对象编程(OOP)和泛型编程都能处理在编写程序时不知道类型的情况.不同之处在于:OOP能处理类型在程序运行之前都未知的情况:而在泛型编程中,在编译时就能获知类型了. 前面介绍的容器.迭代器和算法都 ...

  4. java欧拉函数_欧拉函数(总结)

    定义 欧拉函数ϕ(n)是不超过n且和n互质的正整数的个数.欧拉函数φ(n)的作用就是转化,从而简化运算(小性质:n的所有质因子之和=eular(n)*n/2); 下面直观地看看欧拉函数: n 1 2 ...

  5. C++_虚继承_虚函数_纯虚函数(多继承的二义性,多态)

    基本信息 每一个类都有一个虚表,以及虚表指针; 虚表的内容是编译器决定的,虚表中用于存放虚函数的指针, 程序运行时的类型信息等; 每个多态对象都存放着一个指向当前类型的虚表的指针, 该指针在构造函数中 ...

  6. mysql 内联函数_内联函数 - freeboy小亮 - 博客园

    (1)什么是内联函数? 内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内. (2)为什么要引入内联函数? 当然,引入内联函数的主要目的是:解决程序中函数调用的效率问题.另外,前面我们 ...

  7. arg是什么函数_不定参数函数实现var_arg系列的宏

    电驴的源码日志模块有一个叫 DebugLogError 函数,其签名如下: //代码位于easyMule-master/src/WorkLayer/Log.h 55行void DebugLogErro ...

  8. bool函数_有趣的函数绝无仅有

    靠其强大的功能,灵活的语法,丰富而强大的库Python成为了当前市场上靠前的火热编程语言.Python除了拥有众多的第三方库和方法函数外,自身也带有很多非常有趣的函数,用起来堪称优雅.今天主要为大家分 ...

  9. onclick=两个函数_[译]React函数组件和类组件的差异

    [译]React函数组件和类组件的差异 原文: https://overreacted.io/how-are-function-components-different-from-classes/ 在 ...

  10. string.h包含哪些函数_多个函数组合拳专治不规则时间转化难题|Excel134

    小伙伴们好,今天分享一个关于不规则时间转换的小技巧. 这是Excel学员群里的学员提出的,我觉得这个案例很典型,所以分享给大家,希望能够帮助在此方面有同样困惑的小伙伴. 问题描述:计算A列学习时长的小 ...

最新文章

  1. css3运动后留下轨迹尾巴_球磨机的工作原理及机内运动轨迹分析
  2. hbase shell命令扩展(转自http://www.netfoucs.com/cuirong1986/article/details/7986900)
  3. Windows下Memcached的安装与配置
  4. 玩转数据结构从入门到进阶四
  5. Java抽象类与接口的区别
  6. subst命令镜像虚拟磁盘指南(原创)
  7. SAP CDS view的文本格式的源代码是如何被ABAP后台解析的
  8. excel npoi 连接_Net操作Excel_NPOI(示例代码)
  9. 很气很气——在python中切换selenium中的窗口
  10. django-单表的增删改查-用户部门表
  11. SQL Case When Then
  12. KVM Disk Cache简析
  13. 2022春节档新片预售总票房达1.08亿
  14. 【Flink】Flink的 processingTimeTimersQueue 是如何注册数据的
  15. chrome强制使用HSTS原理
  16. C# 使用Newtonsoft.Json 对象转json字符串,json字符串转对象
  17. win7开启不了Aero
  18. 日本互联网 20 年沧桑路
  19. 记忆就是记忆!!不要深究!
  20. 社交之战,结局:被封?,这只是一个开始

热门文章

  1. SQL——Hibernate SQL增删改查
  2. 从零基础入门Tensorflow2.0 ----六、30 kaggle 10 monkeys 基础模型搭建与训练
  3. ArcGIS中修改面图层中相邻面的公共边
  4. 将print的内容保存到txt文本中
  5. python的全局变量和局部变量
  6. python处理遥感数据(NVDI计算、辐射校正)
  7. CSS学习总结(1)——基本介绍
  8. GDAL和GeoPandas的安装
  9. 实习成长之路——SpringBean一:BeanDefinition元信息有什么?除了Bean名称和类型,还有那些Bean的元信息值得关注?
  10. Glide4.0源码全解析(三),into()方法背后的故事