0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

strongerHuang 来源:strongerHuang 作者:C语言与CPP编程 2021-02-17 09:33 次阅读

1 前言

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

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

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

怎样写可重入函数?

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

2 什么是不可重入函数?

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

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

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

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

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

A. 可重入函数

o4YBAF_2ZTuAc1xyAAAeslwkBXY186.jpg

B. 不可重入函数1

o4YBAF_2ZU2AR4Z7AAAkUu9cugE344.jpg

C. 不可重入函数2

pIYBAF_2ZV6AJsskAAAo5ZMEv4M490.jpg

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

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

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

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

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

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

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

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

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

不使用静态局部变量;

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

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

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

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

责任编辑:xj

原文标题:中断函数调用不可重入函数的后果

文章出处:【微信公众号:strongerHuang】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7534

    浏览量

    128865
  • 函数
    +关注

    关注

    3

    文章

    3911

    浏览量

    61313
  • 中断函数
    +关注

    关注

    0

    文章

    13

    浏览量

    5215

原文标题:中断函数调用不可重入函数的后果

文章出处:【微信号:strongerHuang,微信公众号:strongerHuang】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    回调函数(callback)是什么?回调函数的实现方法

    回调函数是一种特殊的函数,它作为参数传递给另一个函数,并在被调用函数执行完毕后被调用。回调
    发表于 03-12 11:46 308次阅读

    GD32 MCU是如何进入中断函数

    用过GD32 MCU的小伙伴们都知道,程序是顺序执行的,但当有中断来的时候程序会跳转到中断函数,执行完中断函数后程序又继续回到原来的位置继续
    的头像 发表于 01-30 09:45 306次阅读
    GD32 MCU是如何进入<b class='flag-5'>中断</b><b class='flag-5'>函数</b>的

    中断函数的基本概念

    单片机:中断函数
    的头像 发表于 12-05 09:08 327次阅读
    <b class='flag-5'>中断</b><b class='flag-5'>函数</b>的基本概念

    如何查看及更改函数/函数块的调用环境

    模块化设计的思想是把一些相似的功能(比如电机控制、阀控制)设计成函数函数块,这样就可以反复调用。其优点是:使程序架构更加清晰,避免重复编写相似功能的代码。不过可能会产生一个疑惑:既然PLC的程序
    的头像 发表于 11-17 09:08 443次阅读
    如何查看及更改<b class='flag-5'>函数</b>/<b class='flag-5'>函数</b>块的<b class='flag-5'>调用</b>环境

    OP-TEE的内核初始化函数调用

    init_primary_helper函数来完成系统运行环境的建立 ,如果系统支持ATF,则该函数会返回OP-TEE的处理句柄,该处理句柄主要包含 • 各种安全监控模式
    的头像 发表于 11-02 18:18 357次阅读
    OP-TEE的内核初始化<b class='flag-5'>函数</b><b class='flag-5'>调用</b>

    Python 简化函数调用的3种技巧

    假设有一个函数,这个函数需要接收4个参数,并返回这4个参数的和: def sum_four (a, b, c, d): return a + b + c + d 如果需要固定最后前三个参数,仅改变
    的头像 发表于 11-01 16:20 174次阅读

    hal库的中断回调函数可以重入吗?

    不能实现中断回调函数重入
    发表于 10-15 11:32

    python定义函数调用函数的顺序

    定义函数调用函数的顺序 函数被定义后,本身是不会自动执行的,只有在被调用后,函数才会被执行,得
    的头像 发表于 10-04 17:17 586次阅读

    python函数函数之间的调用

    函数函数之间的调用 3.1 第一种情况 程序代码如下: def x ( f ): def y (): print ( 1 ) return y def f (): print
    的头像 发表于 10-04 17:17 356次阅读

    一文详解python调用函数

    函数被定义后,本身是不会自动执行的,只有在被调用后,函数才会被执行,得到相应的结果。但是在 Python 中我们要注意一个关键点,就是Python不允许前向引用,即在函数定义之前,不允
    发表于 10-01 10:45 239次阅读

    通过函数指针调用函数,需不需要加星号?

    先来说下结论,不管是获取函数地址,还是通过函数指针调用函数,两种写法都可以,就用法上来说,没有什么区别,初学者也不必过多纠结。
    的头像 发表于 09-05 17:05 698次阅读

    单片机用按钮中断函数

    单片机用按钮中断函数  单片机中断是一种能够使单片机响应外部信号的机制,这种机制允许单片机在处理其他任务时去响应中断信号,从而提高单片机的性
    的头像 发表于 09-01 10:17 990次阅读

    调用SCL函数块-事例

    在以下部分中,将在组织块“Main” 中调用 SCL 函数块“SCL_Best_before_date” 并互连输入和输出参数。
    的头像 发表于 08-10 09:51 562次阅读
    <b class='flag-5'>调用</b>SCL<b class='flag-5'>函数</b>块-事例

    C函数调用机制与栈帧原理详解

    当一个C函数调用时,函数的参数如何传递、堆栈指针如何变化、栈帧是如何被建立以及如何被消除的,一直缺乏系统性的理解,因此决定花时间学习下函数调用
    发表于 06-08 10:49 567次阅读
    C<b class='flag-5'>函数</b><b class='flag-5'>调用</b>机制与栈帧原理详解

    SCL中调用函数的示例

    在此,可插入函数 (FC) 调用函数块 (FB) 调用函数块可作为单实例、多重实例或参数实例进行调用
    的头像 发表于 06-06 10:18 1353次阅读