关注+星标公众,不错过精彩内容

转自 | C语言与CPP编程

1 前言

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

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

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

  • 怎样写可重入函数?

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

2 什么是不可重入函数?

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

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

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

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

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

A. 可重入函数

void strcpy(char *lpszDest, char *lpszSrc)
{while(*lpszDest++=*lpszSrc++);///< 使用的局部变量*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;

------------ END ------------

推荐阅读:

精选汇总 | 专栏 | 目录 | 搜索

精选汇总 | ARM、Cortex-M

精选汇总 | ST工具、下载编程工具

关关注微信公众号『嵌入式专栏』,底部菜单查看更多内容,回复“加群”按规则加入技术交流群。

点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

中断函数调用不可重入函数的后果相关推荐

  1. 什么是可重入函数和不可重入函数

    可重入函数 在 实时系统的设计中,经常会出现多个任务调用同一个函数的情况.如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任 务调用这个函数的数据,从而导致不可预料 ...

  2. C语言之可重入函数 和不可重入函数

    可重入函数 在 实时系统的设计中,经常会出现多个任务调用同一个函数的情况.如果这个函数不幸被设计成为不可重入的函数的话, 那么不同任务调用这个函数时可能修改其他任 务调用这个函数的数据,从而导致不可预 ...

  3. 可重入函数与不可重入函数(转)

    转自:http://www.cppblog.com/franksunny/archive/2007/08/03/29269.html 主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数 ...

  4. UNIX再学习 -- 可重入函数和 SIGCHLD 语义

    一.可重入函数 参与信号处理的函数必须是可重入函数. 1.何为重入? 假设进程的住控制流程此刻正在调用 foo 函数,就在 foo 函数刚执行到一半的时候,内核向进程递送了信号 a:假设进程对信号 a ...

  5. 【Linux系统编程】可重入和不可重入函数

    00. 目录 文章目录 00. 目录 01. 不可重入函数 02. 可重入函数 03. 判断条件 04. Linux常用可重入函数 05. 附录 01. 不可重入函数 在实时系统的设计中,经常会出现多 ...

  6. 【Linux系统编程】可重入函数和不可重入函数

    在实时系统的设计中,经常会出现多个任务调用同一个函数的情况.如果有一个函数不幸被设计成为这样:那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果.这样的函数是不安全的 ...

  7. 可重入函数与不可重入函数

    主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误:而不可重入的函数由于使 ...

  8. Linux进程信号(产生、保存、处理)/可重入函数概念/volatile理解/SIGCHLD信号

    首先区分一下Linux信号跟进程间通信中的信号量,它们的关系就犹如老婆跟老婆饼一样,没有一毛钱的关系. 信号的概念 信号的概念:信号是进程之间事件异步通知的一种方式,属于软中断.比如:红绿灯是一种信号 ...

  9. [ Linux ] 可重入函数,volatile 关键字,SIGCHLD信号

    目录 1.可重入函数 2.volatile 2.1从信号角度理解volatile的作用 2.2volatile的作用 3.SIGCHLD信号 3.1SIGCHLD信号的验证 1.可重入函数 在数据结构 ...

最新文章

  1. 【百度之星2017】资格赛-题3-度度熊与邪恶大魔王
  2. 对于量子计算来说,99%的准确度足够吗?
  3. SSM中shiro的基本使用
  4. 纯文本邮件转为html,将纯文本电子邮件转换为HTML邮件
  5. 关节点和重连通分量,trajan算法实现(python)
  6. 安卓中bundle的使用
  7. [Leetcode][JAVA][第1111题][栈思想]
  8. MVVM更容易内存泄露吗?
  9. 如何参悟Java的三大框架
  10. 荣耀Play3新版曝光:麒麟710A加持 其他配置不变
  11. hadoop安装小记
  12. 关于OC中的block自己的一些理解(一)
  13. Lucene中的各种consumer
  14. 基于各国贷款数据的可视化分析(含python代码)
  15. Linux刻录系统文件ISO到光盘
  16. 1、二进制安装k8s
  17. 7種解決方案修復請將磁片插入磁碟機
  18. Blueprint介绍和使用
  19. 预览pdf时,中文乱码
  20. 科技论文的图题翻译,图例,图坐标轴

热门文章

  1. apache kafka系列之broker内部架构
  2. java课程设计代码_JAVA课程设计(示例代码)
  3. CentOS 安装 MongoDB 客户端(命令行shell)
  4. Mysql的B+树高度计算
  5. python笔记手写照片_Python笔记-将图片转换为字符画
  6. 王者荣耀s18服务器维护中,王者荣耀:S18开启仅20天,三大数值怪引发众怒,天美也束手无策...
  7. Pycharm从一个断点运行到下一个断点
  8. linux获取电信超级密码吗,最简单获取电信光猫超级帐号及密码
  9. HTML代码实现一些特殊符号的编写
  10. 不使用pinyin4j, 通过字符串截取手段快速查询通讯录联系人的拼音(包括全拼和简拼)