为什么不能在中断中使用printf--不可重入函数

一个人想着一个人 提交于 2019-12-17 08:07:37

前言

前两天在笔试的时候遇到了关于能否在中断中使用printf的问题,当时有点蒙,笔试结束后查阅了资料,这里进行以下总结

可重入函数和不可重入函数

printf不能在中断中被调用的原因是它是一个不可重入函数,而在中断中要避免调用不可重入函数,首先我们先说说什么是可重入函数,什么是不可重入函数
简单说来,区分一个函数是否可重入就是看这个函数能否在未返回的时候再次被调用。而造成一个函数不可重入的原因往往是使用了全局变量,如果一个函数未返回再执行一次会导致对全局变量的操作是不安全的。就例如我们常用的printf、malloc、free都是不可重入的函数,printf会引用全局变量stdout,malloc,free会引用全局的内存分配表,在多线程的环境下,如果没有很好的处理数据保护和互斥访问,就会发生错误
在unix里面通常都有加上_r后缀的同名可重入函数版本
如果实在没有,不妨在可预见的发生错误的地方尝试加上保护锁同步机制等等

如何写可重入的函数

我们只要遵循几条规则,写出来的函数就是可重入的:

  • 不要使用全局变量。因为别的代码很可能覆盖这些变量值
  • 在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”或者用OS_ENTER_KERNAL/OS_EXIT_KERNAL来描述
  • 不能调用任何不可重入的函数
  • 谨慎使用堆栈。最好先在使用前先OS_ENTER_KERNAL

总而言之我们就是要保证中断是安全的!

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

  • 函数体内使用了静态的数据结构;
  • 函数体内调用了malloc()或者free()函数;
  • 函数体内调用了标准I/O函数。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!