1 前言
最近在公司维护的项目中碰到一个解决了定位很久的 bug , bug 找到的时候发现犯了很低级的错误——在中断处理函数中调用了 printf 函数,因为中断处理函数的调用了不可重入函数,导致中断丢失和系统位置错误,这里直接导致嵌入式 linux 系统应用进程中的所有线程停掉,进而导致看门狗进程得不到喂狗,设备重启。
就以上三个问题展开小短文:
2 什么是不可重入函数?
可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入 OS 调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。
满足下列条件的函数多数是不可重入的:
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 如何写出可重入的函数?
本文转载自微信公众号「 C语言与CPP编程」,可以通过以下二维码关注。转载本文请联系 C语言与CPP编程公众号。
什么是批量计算 批量计算(BatchCompute)是一种适用于大规模并行批处理作业的分...
【51CTO.com原创稿件】作为新一轮科技革命和产业变革的核心驱动力,人工智能正在...
混合云平台的优势 创造价值 大规模采用完整混合多云平台技术和运营模式所创造的...
1.硬件配置问题 通过“控制面板”可以完成一般硬件的添加和设备管理等工作,但有...
在网页的HEAD部分中包含有许多内置标签,规范填写这些标签,非常有助于网站的推...
使用场景 您可以创建安全组并定义安全组中的规则,将虚拟私有云中的实例划分成不...
1.我喝了那么多次优乐美奶茶,也没见周杰伦问我是他的谁 2.以后谁敢欺负我,就...
调用DescribeCloudAssistantStatus查询一台或者多台实例是否安装了云助手客户端...
漏洞扫描服务支持扫描的漏洞有: 弱口令检测 SSH、FTP、RDP、SMB、MYSQL、MSSQL...
1.服务器托管又称主机托管 现在市场上,主机托管的价格参差不一,同样托管1U主机...