从|转移C语言和CPP编程1前言我最近在公司维护的项目中遇到了一个已修复了很长时间的错误。
发现错误后,发现发生了非常低级的错误-在中断处理函数中调用了printf函数,因为中断处理函数调用了非可重入函数,从而导致中断丢失和系统位置错误。
这直接导致嵌入式linux系统应用程序进程中的所有线程停止,进而导致看门狗进程无法喂狗,并且设备重新启动。
那么什么是不可重入函数?为什么中断处理程序不能直接调用非可重入函数?如何编写可重入函数?就以上三个问题开始一篇简短的文章:2什么是不可重入函数?可重入函数主要用于多任务环境中。
可重入功能只是可以中断的功能,也就是说,可以在执行此功能期间随时将其中断,然后将其转移到OS中以进行执行。
一段代码,返回控制不会有错误;非可重入函数使用某些系统资源,例如全局变量区,中断向量表等,因此,如果该函数被中断,则可能会发生问题。
函数不能在多任务环境中运行。
满足以下条件的大多数函数都不是可重入的:函数主体中使用了静态数据结构;在函数体中调用malloc()或free();在功能体中调用标准I / O功能; A.是可重入函数void&strcpy(char ** lpszDest,& char& nbsp; * lpszSrc)& nbsp; {while(* lpszDest ++ = * lpszSrc ++); ///<使用的局部变量* dest = 0; } B。
不重新输入功能1char& cTemp;& nbsp;& nbsp;& nbsp; ///<全局变量void SwapChar1(char * lpcX,char * lpcY){cTemp = * lpcX; * lpcX = * lpcY; lpcY = cTemp; // /& lt;全局变量访问} C。
非重入函数2 void& nbsp; SwapChar2(char& nbsp; * lpcX,char& nbsp; * lpcY){& nbsp;& nbsp;& nbsp;& nbsp; static& nbsp; char& nbsp; cTemp;& nbsp; ///<静态局部变量cTemp = * lpcX; * lpcX = * lpcY; lpcY = cTemp; ///& lt;使用静态局部变量} 3为什么中断处理程序不能直接调用非可重入函数?在多任务系统中,中断可能在任务执行期间的任何时间发生;如果某个函数的执行被中断,则该函数所依赖的环境在还原到要执行的断点的过程中没有更改,则该函数为可重入的,否则不能为可重入的。
您不必在中断之前和之后保存并还原上下文吗?功能所依赖的环境如何变化?我们知道,某些上下文在中断时会保存,但仅限于少量上下文,例如返回地址,cpu寄存器等,以及函数的内部使用(例如全局或静态变量,缓冲区等)。
没有被保护,所以如果这些值在函数中发生在中断期间的更改,那么当函数返回到断点以继续执行时,结果是不可预测的。
如果在中断处理函数中调用了由互斥锁保护的全局变量,则在另一个线程正在调用该变量时,中断处理函数将无法及时返回,从而导致严重的问题,例如中断丢失。
而且,在多线程环境中使用时,在不锁定的情况下并发地读取和写入同一内存块将导致诸如段错误/核心转储之类的问题。
总而言之,中断处理程序函数越简单越好。
4如何编写可重入函数?这些全局变量不在函数主体中访问;如果必须访问全局变量,请记住使用互斥信号量来保护全局变量。
或者在调用该函数之前关闭中断,然后在调用之后打开中断;不要使用静态局部变量;坚持只使用默认状态(自动)局部变量;与硬件交互时,请记住关闭硬件中断。
完成交互后,请记住打开中断。
在某些系列中,这被称为“进入/退出核心”。
或由OS_ENTER_KERNAL / OS_EXIT_KERNAL描述;您不能调用任何非可重入函数;小心使用堆栈。
最好在使用前使用OS_ENTER_KERNAL;免责声明:本文内容经21ic授权后发布,版权归原始作者所有。
该平台仅提供信息存储服务。
本文仅代表作者的个人观点,并不代表该平台的立场。
如有任何疑问,请联系