最近在公司维护的项目中碰到一个解决了定位好久的 bug , bug 找到的时候发现犯了很低级的错误——在中断处理函数中调用了 printf 函数,由于中断处理函数的调用了不可重入函数,致使中断丢失和系统位置错误,这里直接致使嵌入式 linux 系统应用进程中的全部线程停掉,进而致使看门狗进程得不到喂狗,设备重启。linux
就以上三个问题展开小短文:c++
可重入函数主要用于多任务环境中,一个可重入的函数简单来讲就是能够被中断的函数,也就是说,能够在这个函数执行的任什么时候刻中断它,转入 OS 调度下去执行另一段代码,而返回控制时不会出现什么错误;而不可重入的函数因为使用了一些系统资源,好比全局变量区,中断向量表等,因此它若是被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。segmentfault
知足下列条件的函数多数是不可重入的:数据结构
void strcpy(char *lpszDest, char *lpszSrc)
{
while(*lpszDest++=*lpszSrc++);///< 使用的局部变量
*dest=0;
}
char cTemp; ///< 全局变量
void SwapChar1(char *lpcX, char *lpcY)
{
cTemp=*lpcX;
*lpcX=*lpcY;
lpcY=cTemp; ///< 访问了全局变量
}
void SwapChar2(char *lpcX,char *lpcY)
{
static char cTemp; ///< 静态局部变量
cTemp=*lpcX;
*lpcX=*lpcY;
lpcY=cTemp; ///< 使用了静态局部变量
}
在多任务系统下,中断可能在任务执行的任什么时候间发生;若是一个函数的执行期间被中断后,到从新恢复到断点进行执行的过程当中,函数所依赖的环境没有发生改变,那么这个函数就是可重入的,不然就不可重入。多线程
在中断先后不都要保存和恢复上下文吗,怎么会出现函数所依赖的环境发生改变了呢?咱们知道中断时确实保存一些上下文,可是仅限于返回地址,cpu 寄存器等之类的少许上下文,而函数内部使用的诸如全局或静态变量,buffer 等并不在保护之列,因此若是这些值在函数被中断期间发生了改变,那么当函数回到断点继续执行时,其结果就不可预料了。并发
在中断处理函数中调用有互斥锁保护的全局变量,若是刚好该变量正在被另外一个线程调用,会致使中断处理函数不能及时返回,致使中断丢失等严重问题。ide
而且在多线程环境中使用,在没有加锁的状况下,对同一段内存块进行并发读写,就会形成 segmentfault/coredump 之类的问题。函数
总而言之,中断处理函数作的事情越简单越好。url