在嵌入式开发软件中回调函数是经常接触的一种软件设计方法,像我们的事件处理机制基本上都会使用到回调函数。
那么就抽了点时间来聊聊他们:
什么是回调函数?
在C语言中,回调函数其实与函数指针的调用在语法上并没有太大的差异,而为什么叫回调函数主要还是从功能上给它起的名字,即这个函数会被"返回来调用"。
而这里所谓的“返回”就涉及到一个方向性问题,从哪里来到哪里去。而在软件中通常就是与“分层设计思想”挂钩的。
在软件设计领域分层设计方式是非常广泛的,在嵌入式中最简单的分层就是两层"驱动层"和“应用层”。
当函数功能上进行分层以后不应该直接在底层驱动中直接调用应用层函数等,比如应用程序通过调用驱动层接口获得物理量数据,我们常规的做法大部分都是不断的轮询相应的API接口返回数据,这样可能会导致不断的IO操作,效率相对比较低下。
那么应用程序是否可以化主动为被动呢,一直舔狗实在是太累了?既然你现在不想搭理我,那等你准备好了,再来告诉我吧,到时候调用我给你的函数就可以了,这个函数已经放在了传给你的函数指针里了,那么这里应用程序所给的函数就是回调函数。
比如我们经常会在应用程序中查询按键是否被按下,然后得编写一大堆的时序等等,还与应用逻辑耦合在一起。
其实按键是是如何检测被按下的过程对于应用程序它并关心,底层程序查询确定好状态给应用程序一个是否按下的通知或者状态即可。
此时底层按键检测程序要通知应用程序,就可以通过相应的回调函数来通知应用层并处理即可。
如果还有点难理解,可以看看stm32使用hal库,你会发现在中断中有大量的回调函数指针被调用,其实回调函数的效果与中断服务函数的执行效果是类似的,hal库中使用回调函数的方式把中断的相关事件服务处理交给了用户自身来注册。
把中断看成一种事件类型,那么回调函数的使用其实就类似于一种事件驱动机制。
同步与异步调用
首先要理清楚这两种方式需要理解什么是同步和异步。
同步调用表示当调用一个底层接口,必须回调函数被执行完毕,不然该接口会一直处于堵塞状态没办法返回结果,且程序无法往下执行。
异步调用表示当调用一个底层接口以后,不需要等待回调函数执行完毕,便可以直接返回继续做下面的事情,最终底层准备好以后便会执行回调函数处理应用层事务,所以我们也称这种回调函数为异步回调函数。
而异步调用的好处在于调用函数不需要阻塞可以继续执行,从而大大提高程序运行效率,但由于异步回调函数在时间上是无序的,导致当我们需要异步调用函数能够顺序执行时便会存在难度,使得业务逻辑比较复杂,难以理解。
为了保证回调的有序性,就需要以上一次回调的结果作为本次异步调用的条件,导致代码一层嵌套一层非常的冗长,类似于ifelse里面再嵌套ifelse之势,所以也很多人称这种方式为 Callback hell(回调地狱)。
为了改善这种结构,通常会采用协程的概念去处理异步回调来规避该问题。对于异步调用常与多线程进行结合,在另外一个线程中执行异步操作,然后调用回调函数返回结果并继续处理。
原文标题:嵌入式软件中回调函数同步与异步调用
文章出处:【微信公众号:strongerHuang】欢迎添加关注!文章转载请注明出处。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !