我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何理解可重入函数

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何理解可重入函数

本篇内容介绍了“如何理解可重入函数”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

 1 前言

最近在公司维护的项目中碰到一个解决了定位很久的 bug , bug 找到的时候发现犯了很低级的错误——在中断处理函数中调用了 printf  函数,因为中断处理函数的调用了不可重入函数,导致中断丢失和系统位置错误,这里直接导致嵌入式 linux  系统应用进程中的所有线程停掉,进而导致看门狗进程得不到喂狗,设备重启。

  • 那什么是不可重入函数呢?

  • 为什么中断处理函数不能直接调用不可重入函数?

  • 怎样写可重入函数?

就以上三个问题展开小短文:

2 什么是不可重入函数?

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

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

  • 函数体内使用了静态(static)的数据结构;

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

  • 函数体内调用了标准 I/O 函数;

A. 可重入函数

void strcpy(char *lpszDest, char *lpszclass="lazy" data-src)  {     while(*lpszDest++=*lpszclass="lazy" data-src++);///< 使用的局部变量     *dest=0; }

B. 不可重入函数1

char cTemp;    ///< 全局变量 void SwapChar1(char *lpcX, char *lpcY)  {     cTemp=*lpcX;     *lpcX=*lpcY;     lpcY=cTemp;   ///< 访问了全局变量 }

C. 不可重入函数2

void SwapChar2(char *lpcX,char *lpcY) {     static char cTemp;  ///< 静态局部变量     cTemp=*lpcX;     *lpcX=*lpcY;     lpcY=cTemp;   ///< 使用了静态局部变量 }

3 为什么中断处理函数不能直接调用不可重入函数?

在多任务系统下,中断可能在任务执行的任何时间发生;如果一个函数的执行期间被中断后,到重新恢复到断点进行执行的过程中,函数所依赖的环境没有发生改变,那么这个函数就是可重入的,否则就不可重入。

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

在中断处理函数中调用有互斥锁保护的全局变量,如果恰好该变量正在被另一个线程调用,会导致中断处理函数不能及时返回,导致中断丢失等严重问题。

并且在多线程环境中使用,在没有加锁的情况下,对同一段内存块进行并发读写,就会造成 segmentfault/coredump 之类的问题。

总而言之,中断处理函数做的事情越简单越好。

4 如何写出可重入的函数?

  • 在函数体内不访问那些全局变量;

  • 如果必须访问全局变量,记住利用互斥信号量来保护全局变量。或者调用该函数前关中断,调用后再开中断;

  • 不使用静态局部变量;

  • 坚持只使用缺省态(auto)局部变量;

  • 在和硬件发生交互的时候,切记关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”或者用  OS_ENTER_KERNAL/OS_EXIT_KERNAL 来描述;

  • 不能调用任何不可重入的函数;

  • 谨慎使用堆栈。最好先在使用前先 OS_ENTER_KERNAL;

“如何理解可重入函数”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何理解可重入函数

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Linux 中可重入函数与不可重入函数详解

Linux 中可重入函数与不可重入函数详解 可重入函数和不可重入函数说起来有点拗口,其实写过多进程(线程)程序的人肯定很快就能明白这两种函数是个神马东西。下面是我对这两个函数的理解:可重入函数可以理解为是能被中断的函数,并且它被中断返回后也
2022-06-04

Linux中可重入函数与不可重入函数的示例分析

这篇文章主要为大家展示了“Linux中可重入函数与不可重入函数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux中可重入函数与不可重入函数的示例分析”这篇文章吧。Linux 中可
2023-06-09

如何分析Linux多线程可重入函数

如何分析Linux多线程可重入函数,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Reentrant和Thread-safe在单线程程序中,整个程序都是顺序执行的,一个函数在同一
2023-06-28

C++ 函数可以重载吗?如何重载?

函数重载允许在一个类或结构中创建同名但参数列表不同的多个函数,针对不同的参数组合提供特定行为。语法如下:定义返回类型、函数名和第一个参数列表。定义返回类型、函数名和第二个参数列表。可继续定义更多具有不同参数列表的重载函数。C++ 函数重载:
C++ 函数可以重载吗?如何重载?
2024-04-21

c++不可重入函数有哪些

不可重入函数是不能同时被多个线程调用的函数,c++ 标准库中的某些函数是不可重入的,包括输入/输出流对象、时间和日期函数、信号处理函数、某些数学函数、环境变量函数、文件系统函数。在多线程程序中应避免使用不可重入函数,如果无法避免,可采取互斥
c++不可重入函数有哪些
2024-04-22

如何深入理解Matplotlib3D 绘图函数plot_surface

这篇文章给大家介绍如何深入理解Matplotlib3D 绘图函数plot_surface,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。今晚开始接触 Matplotlib 的 3D 绘图函数 plot_surface,真
2023-06-20

如何创建可重用的 C++ 函数模板?

函数模板可用于创建可适用于多种数据类型的函数,只需指定使用的类型即可,从而节省时间并减少重复代码。具体步骤如下:使用指定数据类型。指定返回类型。命名函数。指定参数列表。如何创建可重用的 C++ 函数模板函数模板使您能够创建可用于多种类型数
如何创建可重用的 C++ 函数模板?
2024-04-15

如何在 PHP 中创建可重用的函数?

在 php 中创建可重用的函数的步骤包括:使用 function 关键字定义函数。通过函数名和参数调用函数。使用默认参数以省略某些参数。将函数作为参数传递给其他函数(高阶函数编程)。实战案例:通过使用可重用 add 函数轻松计算数组中数字的
如何在 PHP 中创建可重用的函数?
2024-04-10

C++ 函数命名:如何处理重载函数和同名函数

重载函数和同名函数的命名规则不同。重载函数通过区分参数类型来命名,而同名函数通过命名空间来分组。实战案例:重载字符串比较函数使用不同的参数类型进行区分,而不同命名空间的 abs() 函数则使用命名空间缩写或前缀来分组。为了避免命名冲突,建议
C++ 函数命名:如何处理重载函数和同名函数
2024-05-03

Golang泛型如何扩展函数的可重用性?

go 泛型是一种特性,通过参数化类型,使代码可重用,包括:类型安全的集合:可创建存储不同类型元素的集合。通用的比较函数:可比较任何实现了 comparable 接口的类型。Go 泛型:扩展函数可重用性的利器简介在 Go 1.18 版本中
Golang泛型如何扩展函数的可重用性?
2024-04-16

C++ 重载函数的声明:理解函数签名重用的原理

重载函数允许在同一作用域内创建具有相同名称但不同参数列表的多个函数,从而实现代码重用和灵活性:函数签名包含函数名称和参数列表,用于唯一标识函数。参数列表可以包含基本数据类型、类类型、引用类型和指针类型。编译器根据实际参数匹配最佳匹配的函数签
C++ 重载函数的声明:理解函数签名重用的原理
2024-05-02

Golang中怎么实现一个不可重入函数

Golang中怎么实现一个不可重入函数,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。场景用例某个服务是对某些条件进行轮询,每秒监视一些状态。我们希望每个状态都可以独立地检查,而
2023-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录