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

    文章

    7604

    浏览量

    136737
  • 函数
    +关注

    关注

    3

    文章

    4329

    浏览量

    62583
  • 中断函数
    +关注

    关注

    0

    文章

    13

    浏览量

    5282

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

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

收藏 人收藏

    评论

    相关推荐

    HAL库的函数调用示例

    HAL(Hardware Abstraction Layer,硬件抽象层)库是STM32等微控制器中常用的库,它为开发者提供了访问和控制硬件设备的接口。以下是一些常用的HAL库函数及其调用示例: 一
    的头像 发表于 12-02 14:01 334次阅读

    定时器回调函数不能用ICACHE_FLASH_ATTR定义?

    非 OS SDK 在中断处理函数中,请勿使用任何 ICACHE_FLASH_ATTR 定义的函数。 请问: 1、定时器和hw定时器的回调函数
    发表于 07-22 06:33

    FreeRTOS如何在中断调用内存分配函数

    最近在玩FreeRTOS,遇到一个问题,就是不知如何在中断调用内存分配函数。pvPortMalloc函数中会调用xTaskResumeAl
    发表于 05-08 08:25

    IAR库函数中断服务程序中无法调用函数是为什么?

    为什么在中断服务函数里无法调用?定义的变量也不能用!求大神帮忙解决问题!子函数怎么写,写到哪,才能用?实在是不知道怎么办了。
    发表于 05-08 08:01

    STVD中断函数如何调用才能放到主函数使用?

    我用的是STVD,一直研究定时器4中断,网上找了很多资料,现在是定时器4中断可以正常工作,但是中断函数只能写在stm8_interrupt_vector.c这个里面,如果写到主
    发表于 04-26 06:25

    STM32中断相应函数不能持续吗?

    在main.c中的测试函数可以使DAC芯片正常输出多路幅值不同的方波电压,将其放到中断it.c文件中,发现只是输出直线型电压,而非方波,请问中断相应函数
    发表于 04-08 07:05

    函数多层调用的主要注意事项分析

    应用方案设计中,开发者经常会碰到某个子函数需要多次多级调用的情况。
    的头像 发表于 03-27 15:36 859次阅读
    子<b class='flag-5'>函数</b>多层<b class='flag-5'>调用</b>的主要注意事项分析

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

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

    STM32cubeIDE PA0口外部中断改变LED灯状态时,GPIO翻转函数放在外部中断回调函数中不被调用怎么解决?

    STM32cubeIDE PA0口外部中断改变LED灯状态时,GPIO翻转函数放在外部中断回调函数中不被调用,放在EXTI0_IRQHand
    发表于 03-12 06:32

    函数指针与回调函数的应用实例

    通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数函数指针可以像一般函数一样,用于调用
    的头像 发表于 03-07 11:13 400次阅读
    <b class='flag-5'>函数</b>指针与回调<b class='flag-5'>函数</b>的应用实例

    内联函数定义 为什么需要内联函数

    inline关键字是C99标准的型关键字,其作用是将函数展开,把函数的代码复制到每一个调用处。
    的头像 发表于 02-19 12:20 541次阅读

    verilog中函数和任务对比

    在verilog中,函数和任务均用来描述共同的代码段,并且在模式内任意位置被调用,提高代码效率,让代码更加的直观,提高代码可读性。但是在实际使用的过程中,函数和任务也存在诸多的不同,下面将对而这进行
    的头像 发表于 02-12 18:43 883次阅读

    中断调用函数IfxCcu6_PwmBc_updateHallPattern时,寄存器MCMOUTS的值为什么不能更新到MCMOUT中?

    中断调用函数IfxCcu6_PwmBc_updateHallPattern时,寄存器MCMOUTS的值为什么不能更新到MCMOUT中
    发表于 02-05 06:32

    linux用gdb调试遇到函数调用怎么办?

    linux用gdb调试遇到函数调用怎么办? 在Linux上使用GDB调试时,遇到函数调用是一个常见的情况。函数
    的头像 发表于 01-31 10:33 714次阅读

    GD32 MCU是如何进入中断函数

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