欢迎来到我司Viking代理产品网站!
当前位置: Viking代理 > 关于重入函数 >
关于重入函数
Viking代理 2025-05-04

1前言最近,我在公司维护的项目中遇到了一个已修复了很长时间的错误。

发现错误后,发现发生了非常低级的错误-在中断处理函数中调用了printf函数,因为未调用中断处理函数。

重入功能会导致中断损失和系统位置错误。

这直接导致嵌入式linux系统应用程序进程中的所有线程停止,进而导致看门狗进程无法喂狗,并且设备重新启动。

那么什么是不可重入函数?为什么中断处理程序不能直接调用非可重入函数?如何编写可重入函数?就以上三个问题开始一篇简短的文章:2什么是不可重入函数?可重入函数主要用于多任务环境中。

可重入功能只是可以中断的功能,也就是说,可以在执行此功能期间随时将其中断,然后将其转移到OS中以进行执行。

一段代码,返回控制不会有错误;非可重入函数使用某些系统资源,例如全局变量区,中断向量表等,因此,如果该函数被中断,则可能会发生问题。

函数不能在多任务环境中运行。

满足以下条件的大多数函数都是不可重入的:函数主体中使用了静态数据结构;在函数体中调用malloc()或free();在功能体中调用标准I / O功能; A.是可重入函数void&strcpy(char& nbsp; * lpszDest,& nbsp; char& nbsp; * lpszSrc)& nbsp; {& nbsp;& nbsp;& nbsp;& nbsp; while(* lpszDest ++ = * lpszSrc ++); ///& lt;& nbsp;使用的局部变量& nbsp;& nbsp;& nbsp; * dest = 0;} B.非可重入函数1 char  cTemp;& nbsp;& nbsp;& nbsp; ///<& nbsp;全局变量void& nbsp; SwapChar1(charap& nbsp; * lpcX, & nbsp; char& nbsp; * lpcY)& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; cTemp = * lpcX;& nbsp;& nbsp;& nbsp;& n ; nbsp; * lpcX = * lpcY;& nbsp;& nbsp;& nbsp; lpcY = cTemp; <& nbsp; ///& lt;& nbsp;访问的全局变量} C.非可重入函数2 void& nbsp; SwapChar2(char& nbsp; * lpcX,char& nbsp ; * lpcY){& nbsp;& nbsp;& nbsp; static& nbsp; char& cTemp;& nbsp; ///& lt;& nbsp;静态局部变量& nbsp;& nbsp;& nbsp;& nbsp; cTemp = * lpcX;& n  & nbsp;& nbsp; * lpcX = * lpcY;& nbsp;& nbsp;& nbsp;& nbsp; lpcY = cTemp;& nbsp;& nbsp;& nbsp; ///& lt;& nbsp;使用的静态局部变量} 3为什么中断处理程序不能直接调用非可重入函数?在多任务系统中,中断可能在任务执行期间的任何时间发生;如果某个函数的执行被中断,则该函数所依赖的环境在还原到要执行的断点的过程中没有更改,则该函数为可重入的,否则不能为可重入的。

您不必在中断之前和之后保存并还原上下文吗?功能所依赖的环境如何变化?我们知道,某些上下文在中断时会保存,但仅限于少量上下文,例如返回地址,cpu寄存器等,以及函数的内部使用(例如全局或静态变量,缓冲区等)。

没有被保护,所以如果这些值在函数中发生在中断期间的更改,那么当函数返回到断点以继续执行时,结果是不可预测的。

如果在中断处理函数中调用了由互斥锁保护的全局变量,则在另一个线程正在调用该变量时,中断处理函数将无法及时返回,从而导致严重的问题,例如中断丢失。

而且,在多线程环境中使用时,在不锁定的情况下并发地读取和写入同一内​​存块将导致诸如段错误/核心转储之类的问题。

总而言之,中断处理程序函数越简单越好。

4如何编写可重入函数?这些全局变量不在函数主体中访问;如果必须访问全局变量,请记住使用互斥信号量来保护全局变量。

或者在调用此函数之前关闭中断,然后在调用之后打开中断;不要使用静态局部变量;坚持只使用默认状态(自动)局部变量;与硬件交互时,请记住关闭硬件中断。

完成交互后,请记住打开中断。

在某些系列中,这被称为“进入/退出核心”。

或由OS_ENTER_KERNAL / OS_EXIT_KERNAL描述;您不能调用任何非可重入函数;我们