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语言
    +关注

    关注

    183

    文章

    7646

    浏览量

    146169
  • 函数
    +关注

    关注

    3

    文章

    4422

    浏览量

    67853
  • 中断函数
    +关注

    关注

    0

    文章

    13

    浏览量

    5677

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    嵌入式开发常用函数速查表

    在嵌入式开发中,掌握常用函数的用法可以大大提高开发效率。无论是单片机初学者还是有一定经验的工程师,熟悉函数库和调用方式都是必备技能。今天,我们为大家整理一份嵌入式开发常用函数速查表,覆
    的头像 发表于 01-19 09:06 469次阅读
    嵌入式开发常用<b class='flag-5'>函数</b>速查表

    瑞萨RA系列FSP库开发实战指南之DMAC中断回调函数

    调用R_DMAC_SoftwareStart函数来发起软件触发请求信号来启动DMAC传输。
    的头像 发表于 12-26 09:25 5056次阅读

    西门子PLC中函数FC的使用方法

    函数函数块作为模块化编程的重要组成部分,在PLC 用户程序中有着相当频繁的应用。两者在生成与使用的过程中都有一定的相似,且都不能单独使用。而需要赋予特定的功能,由组织块(OB)直接
    的头像 发表于 12-19 11:26 4568次阅读
    西门子PLC中<b class='flag-5'>函数</b>FC的使用方法

    中断函数问题

    main.c中:// 适配启动文件cstartup.asm:绑定中断函数中断向量 #define CSCC_INTERRUPT_FUNCTION_ADDR INT_FUNCTION void
    发表于 12-14 21:24

    函数调用性能消耗

    函数调用对于处理器的性能消耗是很小的,只占有函数执行工作中性能消耗的一小部分。参数传入函数变量寄存器中有一定的限制。这些参数必须是整型兼容的
    发表于 12-12 07:50

    内联函数介绍

    内联函数禁用所有的编译选项。使用__inline修饰函数导致函数调用直接替换为函数体。这样代
    发表于 12-12 07:08

    使用setjmp及longjmp函数处理异常

    ,例如在发生错误或异常时,直接跳转到错误处理或资源释放的代码,而不需要逐层返回。setjmp和longjmp函数定义在setjmp.h头文件中,其语法为: int setjmp(jmp_buf
    发表于 12-11 08:00

    回调函数例子的应用

    步骤,这里的的例子就是,利用一个状态机函数(根据不同状态依次调用不同实现方法的函数),通过回调函数的方式依次调用不同的
    发表于 12-11 07:23

    使用信号处理函数

    使用信号处理函数:这是一种用于处理运行时异常的方法,就是在程序中注册一些信号处理函数,用于响应系统或用户发送的一些信号。信号是一种软件
    发表于 12-11 06:40

    如何用函数指针调用函数

    ;please enter a and b:\"); scanf(\"%d%d\",a,b); c = (*p)(a, b);//通过函数指针调用Max函数
    发表于 12-11 06:26

    控制流和函数调用的精细调整

    特性,避免不必要的计算。 函数调用涉及开销,因为它需要保存当前执行环境并跳转到新的执行环境。减少函数调用,尤其是在频繁执行的循环中,可以显著提高性能。 对于简单且频繁
    发表于 11-14 06:32

    深入了解系统调用API:探索操作系统底层的关键接口

    一、前言 为什么用户程序不能直接访问系统内核模式提供的服务? 在linux中,将程序的运行空间分为内核空间与用户空间(内核态和用户态),在逻辑上它们之间是相互隔离的,因此用户程序不能访问内核数据
    的头像 发表于 11-03 09:20 881次阅读

    详解hal_entry入口函数

    当使用RTOS时,程序从main函数开始进行线程调度;当没有使用RTOS时,C语言程序的入口函数main函数调用了hal_entry函数。由
    的头像 发表于 07-25 15:34 2229次阅读

    C语言中的内联函数与宏

    在C编程中,内联函数和宏都用于避免函数调用的开销并编写可复用的逻辑部分,但它们在工作方式和安全性方面存在显著差异。
    的头像 发表于 07-25 15:10 2072次阅读
    C语言中的内联<b class='flag-5'>函数</b>与宏

    为什么中断回调函数不能使用接收中断开启函数

    我看(书是基于stm32f407编写)书上说在串口接收中断回调函数里面不能使用 接收中断开启函数,书上是利用自己创建了空闲
    发表于 05-28 07:19