为何中断里不能调用printf?

初学嵌入式开发,在写驱动的时候,有一条非常经典的戒律:中断服务程序里,不能调用printf,malloc 函数。
当时仅是把其牢记在心,时刻鞭策自己。大致理解就是,这样的函数可能被阻塞,中断中不能调用有可能被阻塞的函数。

也许,大多数开发人员都到此为止,即使个别有思想的,也仅仅是思考一下,这是为什么那?没有完整确切的深入的答案:)

刚才想到这个,并且搜索了许多中文讨论区,回答的也基本上是只言片语:不能阻塞,不能重入。想来越有些糊涂和不全面,这里将自己的思考阐述一下,仅供讨论。

首先,我们要清楚中断发生时,系统的状态如何。一般系统都有特定的中断运行上下文,但不是任务上下文,所以在这个上下文中不能按照普通任务一样调度(也可以在当前任务中断,不同系统可能有所不同),这是中断运行情况。
其次,发生中断时,大多数系统都是把系统中断关闭,尽快处理完再打开。也可以实现中断嵌套,将更高级别的中断打开,但需要很好的处理中断上下文。
最后要明确的是,系统任务调度是什么时候发生。一般都是在任务主动让出,系统定时中断,系统调用中断返回。

printf, malloc等函数,要用到系统全局资源,具体还要看系统底层具体实现。大部分标准的实现应该用到了信号等互斥手段,达到全局同步和共享的目的。也有的可能没有加以多任务保护同步机制,访问其全局资源存在冲突问题。

结合上面说明的情况,可以看出在中断中调用printf,malloc等函数,可能存在几种情况:
。关中断处理时,有可能导致中断休眠。这种情况下,大部分系统都会挂了(有的可能还能调度?很少)。
。中断不关,高优先级的中断还可以产生,还可以调度(系统比较复杂,估计很少)。
。如果不加多任务保护机制,对于全局资源,存在可重入问题。中断可能发生在任何时候任何函数里,全局资源可能存在访问冲突,后果不能预料。

所以,挂起和可重入都有可能发生,具体看系统情况。并且也可以设计避免其发生。但大多数系统都是针对实时多任务的,这个是重点,而不会因为这样的不重要的需求和改变了其本质的工作方式,甚至影响了系统性能。

你可能感兴趣的:(arm-linux)